/* RainFern design tokens -- the single source for type scale and palette.
 * Loaded first by every page; pages must not redefine these.
 *
 * Type: fluid clamps, so one token covers phone through desktop with no
 * per-breakpoint overrides. Floors are deliberate:
 *   - nothing interactive reads below 16px on a phone  (--fs-body floor)
 *   - no label or smallcaps reads below 11px           (--fs-label floor)
 */

/* base reset: lives here, first, so page stylesheets can never load a
   universal rule after the component rules it would fight */
*{ margin:0; padding:0; box-sizing:border-box; }

/* ---- type scale ---------------------------------------------------------- */
:root{
  /* the five canonical steps */
  --fs-label:  clamp(11px, .8vw + 9px,   13px);
  --fs-small:  clamp(13px, 1vw  + 10px,  15px);
  --fs-body:   clamp(16px, 1.5vw + 12px, 19px);
  --fs-h2:     clamp(20px, 2.5vw + 10px, 30px);
  --fs-h1:     clamp(26px, 4vw  + 12px,  40px);
  /* derived steps, so the hierarchy survives the sweep without new literals */
  --fs-micro:  clamp(11px, .6vw + 9.4px, 12px);
  --fs-lead:   clamp(17px, 1.8vw + 13px, 21px);
  --fs-display:clamp(52px, 12vw + 10px,  84px);

  --lh-body: 1.65;
  --lh-tight: 1.3;

  /* layout */
  --measure: 640px;        /* reading column on big screens */
  --measure-wide: 960px;   /* landing, where the stamp rail benefits */
  --tap: 44px;             /* minimum tap target */

  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
}

/* ---- palette ------------------------------------------------------------- */
/* Canonical names. The Pavilion's legacy names (--card/--dim/--gold/
 * --gold-deep) are aliased onto these so its existing rules keep working
 * while reading from one source. --rain and --mot existed only in the
 * Pavilion; they are promoted to global tokens here. */
html[data-theme="dark"], :root{
  --bg:#1a1714; --bg-card:#231f1b; --bg-input:#2a2520;
  --text:#d4cbbf; --text-dim:#8a7f72;
  --border:#332c25; --border-light:#3d352c;
  --amber:#c9a227; --amber-dim:#a8862a;
  --shadow:0 24px 60px rgba(0,0,0,.45);
  --shadow-card:0 1px 0 rgba(255,255,255,.025), 0 10px 26px rgba(0,0,0,.30);
  --rain:#8fb8c9; --mot:#e8842f;
  /* brightened from #4E7A5A (3.62:1) to clear AA at body size while
     staying unmistakably fern */
  --fern-green:#5E8F6A; --rain-blue:#6FA8C9;
}
html[data-theme="light"]{
  --bg:#faf7f0; --bg-card:#fffdf8; --bg-input:#fff;
  --text:#241f18; --text-dim:#6f6656;
  --border:rgba(36,31,24,.13); --border-light:rgba(36,31,24,.09);
  --amber:#8a6d1f; --amber-dim:#a8862a;
  --shadow:0 20px 50px rgba(40,30,20,.09);
  --shadow-card:0 1px 2px rgba(40,30,20,.05), 0 10px 24px rgba(40,30,20,.075);
  --rain:#3f6b7d; --mot:#a8541a;
  --fern-green:#2E6B45; --rain-blue:#3F7086;
}
/* legacy aliases -- Pavilion markup still says --card / --dim / --gold */
:root{
  --card:var(--bg-card);
  --dim:var(--text-dim);
  --gold:var(--amber);
  --gold-deep:var(--amber-dim);
}

/* ---- base ---------------------------------------------------------------- */
html{ -webkit-text-size-adjust:100%; }
body{
  /* The theme was only half-applied on rooms that did not set their own body
     rule: cards used var(--bg-card) and flipped, while the page behind them
     kept the browser default and stayed white. /weather and /admin/users had
     no body rule at all; landing and iching each wrote their own. The token
     source dresses the page now, so a room cannot forget the room. */
  background:var(--bg);
  color:var(--text);
  transition:background .5s ease, color .5s ease;
  font-family:'DM Sans', system-ui, sans-serif;
  font-size:var(--fs-body);
  line-height:var(--lh-body);
}
/* Cormorant Garamond survives only as non-italic display type: page titles
 * and hexagram / card names. Everything else is DM Sans. */
.serif{ font-family:'Cormorant Garamond', Georgia, serif; font-style:normal; }
/* the design carries no italic at all now -- the hard-to-read "cursive" was
   Cormorant italic. Normalise the UA defaults so <em>/<i> cannot reintroduce it. */
em, i, cite, address{ font-style:normal; }

/* interactive text never drops below the body floor on a phone, and every
 * control clears the 44px tap target */
button, input, textarea, select, a.cv-oauth-go, .opt, .sb-pill, .sb-send, .tossbtn{
  font-family:inherit;
  font-size:var(--fs-body);
}
button, .opt, .tossbtn, .sb-send, .next, .pback, .popts button{
  min-height:var(--tap);
}
/* fixed-size switches are controls, not text: they must not inherit the body
   font token or the 44px min-height, which deformed the theme toggle. */
/* ---- theme switch ---------------------------------------------------------
 * The one and only copy. It used to live in landing.html's inline <style>,
 * so /iching -- which includes the same _header.html markup -- rendered the
 * toggle as a bare unstyled button. Shared markup needs shared CSS.
 *
 * Fixed px on purpose: it is a control, not text, so it must not scale with
 * the type tokens.
 */
.rf-theme, .rf-theme *{ font-size:0; }
.rf-theme{
  width:52px; height:28px; min-height:28px; flex:0 0 52px; padding:0;
  border-radius:99px; background:var(--bg-card); border:1px solid var(--border);
  cursor:pointer; position:relative; align-self:center;
  transition:background .25s ease, border-color .25s ease;
}
.rf-theme:hover{ border-color:var(--amber-dim); }
.rf-knob{
  position:absolute; top:2px; left:2px; width:22px; height:22px; border-radius:50%;
  background:var(--amber); color:#1a1714;
  display:flex; align-items:center; justify-content:center;
  transition:transform .25s cubic-bezier(.3,.8,.4,1);
}
.rf-knob svg{ width:12px; height:12px; display:block; }
html[data-theme="light"] .rf-knob{ transform:translateX(24px); }
.rf-sun{ display:none; }
html[data-theme="light"] .rf-sun{ display:block; }
html[data-theme="light"] .rf-moon{ display:none; }
/* 52x28 is the visual; the hit area is expanded to 44px without inflating the
   track, which padding would do */
.rf-theme::after{ content:""; position:absolute; left:0; right:0;
  top:50%; transform:translateY(-50%); height:44px; }

input, textarea, select{ font-size:var(--fs-body); }

/* ---- shared layout ------------------------------------------------------- */
.rf-measure{ max-width:var(--measure); margin-inline:auto; }

/* ---- button system ------------------------------------------------------
 * Three roles, defined once so every room inherits them.
 *   .btn-primary  the committing action  (Vault, Toss, Receive, Next step)
 *   .btn-choice   a fork in the road     (Asking pair, lane pair, toss options)
 *   .btn-back     the top-left pill
 *
 * Every skin states background, colour, border and radius explicitly and
 * turns off the native widget. A <button> with appearance:auto can fall back
 * to the UA's grey slab the moment one of our declarations fails to apply.
 */
/* reset only what is safe to blanket. border is NOT reset here: the reset and
   the skins share specificity, so a border:0 in this list would race the skin
   that needs a border. Each skin states its own. */
button, .btn-primary, .btn-choice, .btn-back{
  -webkit-appearance:none; appearance:none;
  font-family:inherit; cursor:pointer;
}

.btn-primary, .btn-choice{
  display:flex; align-items:center; justify-content:center; gap:10px;
  /* the reading column is 560px; buttons stop well short of it and centre */
  width:100%; max-width:400px; margin-left:auto; margin-right:auto;
  font-size:var(--fs-body); line-height:1.25;
  border-radius:14px; min-height:56px; text-align:center; text-decoration:none;
  transition:transform .12s ease, border-color .2s ease, background .2s ease, box-shadow .2s ease;
}
.btn-primary .e, .btn-choice .e{ font-size:1.3em; line-height:1; }

.btn-primary{
  background:var(--amber); background-color:#c9a227;
  color:#241c06; font-weight:700;
  border-style:none; border-width:0;
  padding:16px 24px; border-radius:14px; min-height:56px;
  box-shadow:0 4px 14px rgba(0,0,0,.35);
}
html[data-theme="light"] .btn-primary{ background-color:#8a6d1f; color:#fffdf8; }
.btn-primary:hover{ filter:brightness(1.06); }
.btn-primary:active{ transform:scale(.98); }
.btn-primary:disabled{ opacity:.55; cursor:default; transform:none; }

.btn-choice{
  background:var(--bg-card); background-color:#231f1b;
  color:var(--text); font-weight:600;
  border-style:solid; border-width:1.5px; border-color:var(--amber-dim);
  padding:16px 20px; border-radius:14px; min-height:56px;
}
html[data-theme="light"] .btn-choice{ background-color:#fffdf8; }
.btn-choice:hover, .btn-choice:focus-visible{ border-color:var(--amber); }
.btn-choice:active{ transform:scale(.98); }

.btn-back{
  display:inline-flex; align-items:center; gap:6px;
  background:transparent; color:var(--text);
  border-style:solid; border-width:1px; border-color:var(--amber-dim); border-radius:99px;
  min-height:44px; padding:10px 18px;
  font-size:var(--fs-small); font-weight:600;
  transition:border-color .2s, color .2s;
}
.btn-back:hover{ border-color:var(--amber); color:var(--amber); }

/* .btn-pill -- the system's small inline button, for nav rows and chips.
   .btn-primary and .btn-choice are full-width cards (width:100%, max-width:400px,
   min-height:56px); either would blow out the header row, which is why the nav's
   Sign in could not simply become .btn-choice. Explicit background and border, so
   it can never fall back to a system default. */
.btn-pill{
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
  background:transparent; color:var(--text);
  border-style:solid; border-width:1px; border-color:var(--border);
  border-radius:99px;
  font-family:inherit; font-size:var(--fs-small); font-weight:500;
  padding:8px 15px; white-space:nowrap; text-decoration:none;
  cursor:pointer; transition:border-color .2s, color .2s;
}
.btn-pill:hover, .btn-pill:focus-visible{ border-color:var(--amber-dim); color:var(--amber); }
.btn-pill:active{ transform:scale(.98); }
/* the nav row is tight on a phone; these mirror the per-page overrides the old
   .ghost carried at the same breakpoints, so retiring it changed no geometry. */
@media (max-width:620px){ .btn-pill{ padding:5px 9px;  font-size:var(--fs-label); } }
@media (max-width:400px){ .btn-pill{ padding:5px 7px;  font-size:var(--fs-label); letter-spacing:0; } }

/* ---- surfaces -------------------------------------------------------------
   Every room was hand-rolling the same card: 1px --border-light on --bg-card.
   /weather alone re-derived it four times and the smallcaps label three. They
   live here now so rooms share one skin instead of each inventing it. Adopted
   by /weather 2026-08-28; older rooms keep their local copies until they are
   swept, which is why this is additive and breaks nothing. */
.rf-card{
  background:var(--bg-card);
  border-style:solid; border-width:1px; border-color:var(--border-light);
  border-radius:16px;
  padding:15px 16px;
  /* paired across themes: dark lifts by darkening, cream by a soft warm cast,
     so a card sits the same distance off the page in both. Without this the
     light theme was cream-on-cream and read as flat. */
  box-shadow:var(--shadow-card);
}
.rf-eyebrow{
  font-size:var(--fs-label); letter-spacing:.18em; text-transform:uppercase;
  font-weight:500; margin:0 0 8px; color:var(--text);
}

/* stacked choices share one rhythm */
.btn-stack{ display:flex; flex-direction:column; gap:12px; width:100%; }
.btn-grid2{ display:grid; grid-template-columns:1fr 1fr; gap:12px;
  width:100%; max-width:400px; margin-left:auto; margin-right:auto; }
/* inside the 2x2 the cells are already narrow -- one step down keeps
   "2 heads · 1 tail" on a single line at 390px */
.btn-grid2 .btn-choice{ max-width:none; font-size:var(--fs-small); padding:14px 10px; }
/* the step-forward button always has air above it */
/* the step-forward button always has air above it. Class-based, because the
   reading code reassigns className on #nextBtn as it advances cards. */
.btn-step{ margin-top:20px; }
/* a label too long for one line at 390px steps its own font down; the button
   keeps its width so the row stays even */
.btn-choice.btn-long{ font-size:var(--fs-small); }

/* ---- the room title row (templates/_roomtitle.html) -----------------------
   One line per room: the field bar's glyph, the room's name, and the way to
   ask what the room is. The name's type is the house rule .room-h1 — it was
   .pv-h1 on the Pavilion and is promoted here so every room reads the same.
   Date lines and subtitles are not part of a title row (Rob, 2026-09-18). */
/* Three groups. The name group is centred on the ROW, not on what is left of
   it, so the aside's caption can grow without shoving the title sideways —
   which is why the aside is taken out of the flow rather than laid beside it. */
.room-title{ position:relative; display:flex; align-items:center;
  justify-content:center; min-height:var(--tap); margin:2px 0 12px; }
.room-title-main{ display:inline-flex; align-items:center; gap:7px; min-width:0; }
.room-title .room-aside-wrap{ position:absolute; right:0; top:50%;
  transform:translateY(-50%); }
.room-emoji{ font-size:var(--fs-h2); line-height:1; flex-shrink:0; }
.room-h1{ font-size:var(--fs-h1); letter-spacing:.06em; color:var(--text);
  margin:0; line-height:1.15; font-weight:400; }
/* The aside: a filled gold control, because its sheet is one a traveller
   CHANGES something in. The ⓘ below stays quiet grey, because its sheet is one
   they only read. Two roles, two weights, decided once here. */
.room-aside-wrap{ display:inline-flex; flex-direction:column; align-items:center;
  gap:1px; flex-shrink:0; }
.room-aside{ width:var(--tap); height:var(--tap); min-width:var(--tap);
  display:flex; align-items:center; justify-content:center; padding:0;
  background:none; border:0; cursor:pointer;
  -webkit-appearance:none; appearance:none; }
/* 44px of tap around a 36px face: §6's minimum and Rob's 36px button, both. */
.room-aside-face{ width:36px; height:36px; border-radius:50%;
  background:var(--amber); color:#1a1714;
  display:flex; align-items:center; justify-content:center;
  font-size:var(--fs-body); line-height:1;
  transition:filter .2s ease; }
.room-aside:hover .room-aside-face{ filter:brightness(1.08); }
.room-aside-cap{ font-size:var(--fs-micro); color:var(--text-dim); line-height:1;
  margin-top:-2px; }

.room-info{ width:var(--tap); height:var(--tap); min-width:var(--tap);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  background:none; border:0; color:var(--text-dim); font-size:var(--fs-lead);
  line-height:1; cursor:pointer; -webkit-appearance:none; appearance:none; }
.room-info:hover{ color:var(--amber); }

.room-sheet{ display:none; position:fixed; inset:0; z-index:70;
  background:rgba(12,10,8,.72); align-items:center; justify-content:center; padding:22px; }
.room-sheet.on{ display:flex; }
.room-sheet-card{ position:relative; width:100%; max-width:392px;
  background:var(--bg-card); border:1px solid var(--border-light);
  border-radius:14px; padding:30px 22px 22px; }
.room-sheet-card p{ margin:0 0 10px; font-size:var(--fs-body); color:var(--text);
  line-height:1.6; }
.room-sheet-card p:last-child{ margin-bottom:0; }
.room-sheet-lead{ color:var(--text); }
.room-sheet-slot{ color:var(--text-dim) !important; font-size:var(--fs-small) !important; }
.room-sheet-x{ position:absolute; top:8px; right:8px; width:var(--tap); height:var(--tap);
  background:none; border:0; color:var(--text-dim); font-size:var(--fs-h2);
  line-height:1; cursor:pointer; -webkit-appearance:none; appearance:none; }

/* ---- the body palette -----------------------------------------------------
   One hue per body, ten of them, the same on both themes: a planet's colour is
   what it is, not a function of the room's light. They are read by the wheel
   and by the planets card on /weather, so the disc on the chart and the glyph
   in the list can never disagree.

   The sky disc itself is dark in both themes because it is the sky. */
:root{
  --body-sun:     #e8b64c;
  --body-moon:    #cfd6e0;
  --body-mercury: #8fc7a8;
  --body-venus:   #e2a3b8;
  --body-mars:    #d2603f;
  --body-jupiter: #d9a05b;
  --body-saturn:  #9a8f7d;
  --body-uranus:  #6fb7c4;
  --body-neptune: #5d7fc4;
  --body-pluto:   #9b7bb0;
  /* the chart ground, both themes */
  --sky-disc:   #121a2e;
  --sky-ring:   rgba(227,184,78,.34);
  --sky-spoke:  rgba(227,184,78,.14);
  --sky-glyph:  rgba(227,184,78,.82);
}
html[data-theme="light"]{
  /* same disc — it is the sky — with a slightly brighter rim so it reads as
     an object on a pale page rather than a hole in it */
  --sky-ring:   rgba(227,184,78,.52);
  --sky-spoke:  rgba(227,184,78,.20);
}

/* ---- the house tile -------------------------------------------------------
   The "explore further" tile. It lived in the Pavilion's own page <style>, and
   when the Lantern grew a row of doors on 2026-09-18 it reused the class names
   without the rules — so the Lantern rendered five unstyled links. Same word,
   two places, which is §3's whole point. It exists once now and both rooms
   read it.

   A room says how many across it wants; it does not restate the tile:
     .xf-row { --xf-cols: 5; --xf-cols-sm: 3; }
   Defaults are the Pavilion's four, dropping to two on a phone. */
.xf-rule{ display:flex; align-items:center; gap:12px; margin:26px 0 12px; }
.xf-rule::before, .xf-rule::after{ content:""; flex:1; height:1px; background:var(--border-light); }
.xf-rule span{ font-size:var(--fs-label); letter-spacing:.14em; text-transform:uppercase;
  color:var(--text-dim); }

.xf-row{ display:grid; grid-template-columns:repeat(var(--xf-cols, 4), 1fr); gap:8px; }
@media (max-width:400px){
  .xf-row{ grid-template-columns:repeat(var(--xf-cols-sm, 2), 1fr); }
}
.xf-tile{ display:flex; flex-direction:column; align-items:center; gap:4px;
  min-height:var(--tap); padding:12px 6px; text-decoration:none;
  background:var(--bg-card); border:1px solid var(--border-light);
  border-radius:12px; color:var(--text); text-align:center;
  font-family:'DM Sans', system-ui, sans-serif; cursor:pointer;
  -webkit-appearance:none; appearance:none; }
a.xf-tile:hover{ border-color:var(--amber-dim); }
.xf-tile.soon{ opacity:.62; cursor:default; }
.xf-ico{ font-size:var(--fs-lead); line-height:1; }
.xf-n{ font-size:var(--fs-label); line-height:1.2; }
.xf-s{ font-size:var(--fs-label); color:var(--text-dim); }

/* ---- the house tab strip --------------------------------------------------
   The segmented control the Sky wears (Today · Natal · Overlap) and the
   Pavilion wears (Cast · Read · History). It was written twice, once in each
   page, and the Lantern now needs it too — so it exists once here and every
   room reads it, the same way the tile does.

   36px by §6's segmented-toggle exception: the law is about target AREA, and a
   segment at least 88px wide clears a 44px button's. min-height:0 is what
   makes 36 real against the global button minimum. Labels never wrap and never
   truncate; a room that cannot fit its labels needs shorter labels, not a
   narrower strip.

   A room may set --seg-max to widen the strip. The optional .seg-back rides
   the same row, left of the segments (§6 stage geometry). */
.seg-row{ display:flex; align-items:center; gap:8px; margin:0 auto;
  max-width:var(--seg-max, 430px); }
.seg-back{ width:36px; height:36px; min-width:36px; min-height:0; flex-shrink:0;
  display:flex; align-items:center; justify-content:center; padding:0;
  font-size:var(--fs-lead); line-height:1; border-radius:999px; }
.seg{ display:flex; gap:2px; padding:2px; flex:1; min-width:0;
  background:var(--bg-input); border:1px solid var(--border); border-radius:999px; }
.seg-b{ flex:1 1 0; min-width:0; height:32px; min-height:0; padding:0 4px; border:0;
  border-radius:999px; background:none; color:var(--text);
  font-family:'DM Sans', system-ui, sans-serif; font-size:var(--fs-micro);
  font-weight:500; white-space:nowrap; cursor:pointer;
  -webkit-appearance:none; appearance:none; transition:background .2s, color .2s; }
.seg-b.on{ background:var(--amber); color:var(--bg); }
/* More tabs than fit: the strip scrolls rather than shrinking the labels. */
.seg.scrolls{ overflow-x:auto; scrollbar-width:none; }
.seg.scrolls::-webkit-scrollbar{ display:none; }
.seg.scrolls .seg-b{ flex:0 0 auto; padding:0 12px; }

/* ── THE SITE FOOTER (fence "Sable's host", 2026-10-09, item 15) ───────────
   The house names its parts here. The Llama 3.1 Community License asks that
   "Built with Llama" be displayed on a related website or user interface; the
   same words are in the header drawer, which is on all 25 pages, and in NOTICE
   at the repo root.
   Tokens only, and --text-dim throughout because a credit line is metadata and
   never body copy (§6's readability law). Phone-first: centred, 16px gutters,
   and no fixed positioning -- the footer is the end of the document, so it can
   never cover an interactive element or Sable's floor. */
.rf-foot{ max-width:640px; margin:0 auto; padding:28px 16px 8px;
  text-align:center; font-size:var(--fs-micro); color:var(--text-dim);
  line-height:1.6; }
.rf-foot p{ margin:0 0 4px; }
.rf-foot-b{ letter-spacing:.08em; }
