/* ==========================================================================
   RIH · design system
   Implements ../design-system.md. Every value is sampled from RIH's real site,
   measured from a named reference, or verified against our vendored libraries.
   Fonts are self-hosted; nothing here touches a CDN.
   ========================================================================== */

/* ---------- FACES (self-hosted, variable where available) ---------------- */

/* Concept One + C: their own stack */
@font-face { font-family: 'Playfair'; src: url('fonts/PlayfairDisplay-Variable.woff2') format('woff2-variations');
             font-weight: 400 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Playfair'; src: url('fonts/PlayfairDisplay-VariableItalic.woff2') format('woff2-variations');
             font-weight: 400 900; font-style: italic; font-display: swap; }
@font-face { font-family: 'Cormorant'; src: url('fonts/CormorantGaramond-Variable.woff2') format('woff2-variations');
             font-weight: 300 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Cormorant'; src: url('fonts/CormorantGaramond-VariableItalic.woff2') format('woff2-variations');
             font-weight: 300 700; font-style: italic; font-display: swap; }

/* Option A: wedge serifs, no sans at all */
@font-face { font-family: 'Neco'; src: url('fonts/Neco-Variable.woff2') format('woff2-variations');
             font-weight: 400 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Recia'; src: url('fonts/Recia-Variable.woff2') format('woff2-variations');
             font-weight: 300 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Recia'; src: url('fonts/Recia-VariableItalic.woff2') format('woff2-variations');
             font-weight: 300 700; font-style: italic; font-display: swap; }

/* Option B: high-contrast sans with a real ligature system */
@font-face { font-family: 'Melodrama'; src: url('fonts/Melodrama-Variable.woff2') format('woff2-variations');
             font-weight: 300 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Amulya'; src: url('fonts/Amulya-Variable.woff2') format('woff2-variations');
             font-weight: 300 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Amulya'; src: url('fonts/Amulya-VariableItalic.woff2') format('woff2-variations');
             font-weight: 300 700; font-style: italic; font-display: swap; }

/* Option C's sans, and the metadata instrument shared by A/B/C */
@font-face { font-family: 'Apfel'; src: url('fonts/ApfelGrotezk-Regular.woff2') format('woff2');
             font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Apfel'; src: url('fonts/ApfelGrotezk-Mittel.woff2') format('woff2');
             font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Apfel'; src: url('fonts/ApfelGrotezk-Fett.woff2') format('woff2');
             font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Bevellier'; src: url('fonts/Bevellier-Variable.woff2') format('woff2-variations');
             font-weight: 100 900; font-style: normal; font-display: swap; }

/* ---------- TOKENS ------------------------------------------------------- */

:root {
  /* colour: RIH's real values. #039be5 is Google's calendar button, never ours. */
  --paper:  #f9f7f2;
  --ink:    #1a1a1a;
  --mid:    #7a7a7a;
  --rule:   #d1cec5;
  --sienna: #552507;   /* their logo ink. The single hue event, roundel only. */
  --black:  #000;

  /* Layout unit: 1u = 16px at a 1920 artboard. Layout scales, text does not
     depend on it, so user font-size preferences survive. */
  --u: calc(100vw / 120);
  --gap: clamp(16px, calc(var(--u) * 2), 32px);   /* gutter AND page inset, always identical */

  /* Motion. Two curves, asymmetric in and out (Obys: entrances long expo-out,
     exits short cubic-in, never a reversed entrance). */
  --ease-enter: cubic-bezier(0.165, 0.84, 0.44, 1);   /* easeOutQuart */
  --ease-move:  cubic-bezier(0.76, 0, 0.24, 1);       /* easeInOutQuart */
  --ease-exit:  cubic-bezier(0.55, 0.085, 0.68, 0.53);/* cubic-in */
  --dur-ui:   .6s;
  --dur-in:   1.2s;
  --dur-out:  .6s;

  /* Semantic z-index. No 999, no 9999. */
  --z-base: 1; --z-raised: 2; --z-overlay: 10; --z-nav: 20; --z-chrome: 30;

  /* Default type roles; each concept overrides these three lines only. */
  --display: 'Playfair', Georgia, serif;
  --accent:  'Cormorant', Georgia, serif;
  --body:    'Apfel', system-ui, sans-serif;
  --meta:    'Apfel', system-ui, sans-serif;
}

/* Text scales with the viewport but keeps a floor and stays user-controllable.
   NOT a vw-derived root font-size: by-kin, Obys and basicagency all ship that,
   and it silently defeats the user's own font-size preference. */
html {
  font-size: clamp(15px, 1.02vw, 22px);
  -webkit-text-size-adjust: 100%;
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-weight: 400;                     /* not 300. Light grey light text is the readability failure. */
  font-size: 1rem;
  line-height: 1.5;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
}

/* `height: auto` is not optional here. Every image in this project carries HTML
   width/height attributes to reserve layout space, and without this reset an
   image given a CSS width renders at its literal height attribute: a 190px-wide
   Library cover came out 190x1600 instead of 190x253. */
img, svg, video { display: block; max-width: 100%; }
img[width][height] { height: auto; }

/* ---------- TYPE SCALE -------------------------------------------------- */
/* Ratios 1.33 / 1.50 / 2.00 / 1.65 / 1.31. One clamp on the root, none below. */

.t-display, .t-h1, .t-h2, .t-stand { text-wrap: balance; }

/* Display ceiling is 6rem. An earlier draft shipped 6.6rem; above 6rem the page
   is shouting rather than designing. */
.t-display { font-family: var(--display); font-size: 6.0rem; line-height: 1.00; font-weight: 500; }
.t-h1      { font-family: var(--display); font-size: 4.5rem; line-height: 1.00; font-weight: 500; }
.t-h2      { font-family: var(--display); font-size: 3.0rem; line-height: 1.05; font-weight: 500; }
.t-stand   { font-family: var(--accent);  font-size: 1.65rem; line-height: 1.25; font-weight: 400; font-style: italic; }
.t-body    { font-size: 1rem;    line-height: 1.50; text-wrap: pretty; }
.t-meta    { font-family: var(--meta); font-size: .76rem; line-height: 1.30; }
.t-label   { font-family: var(--meta); font-size: .65rem; line-height: 1.30; }

@media (max-width: 900px) {
  .t-display { font-size: 3.4rem; }
  .t-h1      { font-size: 2.7rem; }
  .t-h2      { font-size: 1.9rem; }
  .t-stand   { font-size: 1.25rem; }
}

/* Zero letter-spacing. by-kin ships not one non-zero value across eleven
   stylesheets and reads more expensive than anything we made. The only
   exception is a lockup, which is a logo, not text. */
.t-lockup {
  font-family: var(--display); text-transform: uppercase;
  letter-spacing: .30em; font-weight: 500;
}

/* Display tracking. The house floor is -0.04em and it is not negotiable, so the
   earlier -0.05em for grotesques is gone: the reference sites that ship -0.05em
   are neo-grotesques at 250px where it is a sidebearing correction, which is a
   different situation from ours and not a reason to breach our own floor.
   Serif stays looser because Playfair's hairlines collide before that. */
.face-serif  .t-display, .face-serif  .t-h1 { letter-spacing: -0.02em; }   /* Playfair, Neco, Recia */
.face-grot   .t-display, .face-grot   .t-h1 { letter-spacing: -0.04em; }   /* Melodrama, Apfel */

/* Their real device: lowercase growing into caps. The old build commented this
   and then destroyed it with text-transform: uppercase. */
.lc-caps { font-family: var(--display); font-weight: 500; }
.lc-caps > i {
  font-family: var(--accent); font-style: italic; font-weight: 400;
  text-transform: lowercase; font-size: 1.12em;
}
.lc-caps > b { font-weight: 500; text-transform: uppercase; letter-spacing: .04em; }

/* The italic pivot. Cormorant has a smaller x-height and lighter stems than
   Playfair at the same font-size, which is why it read as a rendering error.
   Corrected ONCE here, never per instance. */
.pivot {
  font-family: var(--accent); font-style: italic; font-weight: 400;
  font-size: 1.09em; letter-spacing: .01em;
}

/* Real small caps, never faux uppercase */
.smallcaps { font-variant-caps: all-small-caps; font-feature-settings: "smcp"; letter-spacing: .06em; }
.tnum { font-variant-numeric: tabular-nums; }
.onum { font-variant-numeric: oldstyle-nums; }

/* ---------- GRID -------------------------------------------------------- */
/* 6 columns, 16 at 1200+. No max-width cap: edge to edge with a --gap inset. */

.grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  column-gap: var(--gap);
  padding-inline: var(--gap);
}
@media (min-width: 1200px) { .grid { grid-template-columns: repeat(16, minmax(0, 1fr)); } }

/* The asymmetry idiom: full width on mobile, an offset start on desktop.
   These exact placements are borrowed from by-kin, including 4/13 being
   deliberately off-centre (13, not 14). */
.c-full { grid-column: 1 / -1; }
@media (min-width: 1200px) {
  .c-2-16   { grid-column: 2 / 16; }
  .c-6-end  { grid-column: 6 / -1; }
  .c-4-13   { grid-column: 4 / 13; }
  .c-6-11   { grid-column: 6 / span 11; }
  .c-1-7    { grid-column: 1 / 7; }
  .c-8-end  { grid-column: 8 / -1; }
  .c-bleed-r { grid-column: 12 / -1; margin-right: calc(var(--gap) * -1); }
}

/* Measure by padding, not max-width (The Gentlewoman). The container grows so
   images breathe full width; the paragraph is padded to hold a 72-80ch measure. */
.prose { }
.prose > p { padding-inline: 0; max-width: 74ch; }
@media (min-width: 1200px) {
  .prose > p { padding-inline: calc(var(--u) * 4) 0; max-width: none; width: 46vw; }
  .prose > figure { padding-inline: 0; }
}

/* Exactly two rule weights, one ink */
.rule    { height: 1px; background: var(--ink); border: 0; }
.rule--h { height: 1px; background: var(--rule); border: 0; }
/* stacked bordered rows never render a 2px double hairline */
.stack > * + * { margin-top: -1px; }

/* ---------- REVEALS ----------------------------------------------------- */
/* The hidden start state lives in CSS behind @media (scripting: enabled), NOT
   behind a JS-applied class. Fails safe: if unsupported, the block never
   applies and content stays visible. No flash, no blank page if a script 404s. */

.ln_ { display: block; overflow: hidden; margin-inline: -1px; }  /* room for italics/overhangs */
.ln  { display: block; padding-inline: 1px; padding-bottom: .14em; }

@media (scripting: enabled) {
  .rv    { opacity: 0; }
  .ln    { transform: translateY(103%); }  /* 103%, not 100%: descenders clear the mask */
  .clip  { clip-path: inset(0% 50%); }     /* centre-out, tweened via --clip */
  .wipe  { clip-path: inset(100% 0 0 0); } /* bottom-up */
}

@media (prefers-reduced-motion: reduce) {
  .rv   { opacity: 1 !important; }
  .ln   { transform: none !important; }
  .clip, .wipe { clip-path: none !important; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}

/* ---------- THE TICKER (fixed) ------------------------------------------ */
/* Two sibling runs in a flex container, animating the CONTAINER to -50%.
   The old single-node version left a 304px void at 1440 and 785px at 1920,
   because the run measured 2271px and 50% of it is 1135px. */
.ticker { overflow: hidden; border-block: 1px solid var(--rule); padding-block: calc(var(--u) * .9); }
.ticker__belt { display: flex; width: max-content; animation: belt 44s linear infinite; }
.ticker__run {
  display: flex; gap: calc(var(--u) * 2.4); padding-right: calc(var(--u) * 2.4);
  white-space: nowrap; font-family: var(--meta); font-size: .68rem; color: var(--mid);
  text-transform: uppercase;
}
@keyframes belt { to { transform: translateX(-50%); } }
.ticker:hover .ticker__belt { animation-play-state: paused; }

/* ---------- STATES ------------------------------------------------------ */

a { color: inherit; text-decoration: none; }

/* Underline as an animatable border, never text-decoration. -102% avoids a
   sub-pixel sliver. Retract-then-extend so there is no reversal artefact. */
.ul { position: relative; overflow: hidden; display: inline-block; }
.ul::after {
  content: ''; position: absolute; inset: auto 0 0 0; height: 1px;
  background: currentColor; transform: translateX(-102%);
  transition: transform var(--dur-ui) var(--ease-enter);
}
@media (not (hover: none)) { .ul:hover::after { transform: translateX(0); } }

:focus-visible {
  outline: 1px solid var(--rule); outline-offset: 3px;
}
.on-dark :focus-visible { outline-color: var(--paper); }

/* Hovers never fire on touch */
@media (not (hover: none)) {
  .lift { transition: transform var(--dur-ui) var(--ease-enter); }
  .lift:hover { transform: translateY(-2px); }
  /* Exo Ape: a 1px inset exposing a hairline frame, not a scale-up */
  .inset-hover { transition: inset var(--dur-ui) var(--ease-enter); }
  .inset-hover:hover { inset: 1px; }
}

/* Fixed UI that survives both paper and photography with no JS.
   Obys and by-kin both ship exactly this. */
.blend { mix-blend-mode: difference; color: var(--paper); }
.no-blend { mix-blend-mode: normal; }

/* ---------- IMAGES ------------------------------------------------------ */
.ph { position: relative; overflow: hidden; }
.ph img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }
/* object-position: center top so heads and horizons survive a tightening crop */

/* Concept chrome: identifies which build you are looking at. Not part of the design. */
.chrome {
  position: fixed; inset: auto 0 0 0; z-index: var(--z-chrome);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 8px var(--gap); background: var(--black); color: var(--paper);
  font-family: var(--meta); font-size: .62rem; text-transform: uppercase; letter-spacing: .14em;
}
.chrome nav { display: flex; gap: 14px; flex-wrap: wrap; }
.chrome a { opacity: .5; }
.chrome a[aria-current='true'], .chrome a:hover { opacity: 1; }
