/* ============================================================================
   PAULINA · GALLERY SAMPLES — SHARED DESIGN KIT
   /demo_fable/shared/shared.css
   ----------------------------------------------------------------------------
   Direction: "Sticker Garden" — the winning sticker-pop vocabulary (flat fills,
   one ink outline, hard offset shadows, chunky rounded display type) grafted
   with garden-storybook's colour governance (three-tier tokens, ordered wheel,
   only the accent role ever moves) and soft-editorial's typographic rigour and
   image discipline (one quiet plate sample, height:auto, quarantined artwork
   colour, lightbox→palette "borrow this colour" bridge).

   CONTENTS
     01  Fonts
     02  Colour tokens — the balanced pastel rainbow (10 hues x 4 tiers)
     03  Neutrals, ink, line weights, radii, shadows, spacing, type scale
     04  Lead-hue theme hooks  [data-lead-hue="…"]
     05  Reset + base elements
     06  Typography
     07  Layout: wraps, sections, bands, rainbow rule, hills, scallop
     08  Buttons, chips, pills, badges, eyebrows
     09  The navbar (injected by shared.js — do not rebuild per page)
     10  Cards, photo tiles, swatch rows, keepsake pairs
     11  Flower + sticker decoration utilities
     12  Artist palette widget
     13  Lightbox
     14  Footer
     15  Hue rotation utilities (balance for free)
     16  Reduced motion + print
   ========================================================================== */

/* ---------------------------------------------------------------- 01 Fonts */
/* Three families: Fraunces (display serif), Fredoka (rounded display), Nunito
   (body). They are NOT @imported here. An @import cannot start until this
   sheet has downloaded and parsed, which serialises the critical path
   HTML -> shared.css -> fonts CSS -> woff2 and costs a full round trip before
   any text can paint. Every page therefore carries the request itself, in the
   <head>, immediately after the preconnects and BEFORE this file:

     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:SOFT,WONK,opsz,wght@0..100,0..1,9..144,300..700&family=Fredoka:wght@400..600&family=Nunito:ital,wght@0,400;0,600;0,700;0,800;1,400&display=swap">
     <link rel="stylesheet" href="/demo_fable/shared/shared.css">

   Use that exact family/axis string — the three --font-* stacks below name
   these faces and carry real system fallbacks, and display=swap means text is
   never invisible while they load. Do not re-add an @import here. */

/* ------------------------------------------- 02 The balanced pastel rainbow */
/*  TEN hues so each of the ten samples can lead with a different one.
    Wheel order is FIXED and used for every run of colour on the site:
      coral → peach → butter → lime → mint → aqua → sky → periwinkle → lilac → bubblegum

    Four tiers per hue:
      --c-<hue>   PASTEL     fills, washes, blobs, petals.  All ten sit in the
                             narrow lightness band L* 76.4–83.2 — this is the
                             mechanism that stops one hue shouting over another.
                             Ink clears 7.09:1 on the worst of them, so any
                             pastel can carry ink text.
      --d-<hue>   DEEP       line work, icon strokes, display type >= 28px.
                             All clear 4.5:1 on --ground.
      --t-<hue>   TEXT-SAFE  body copy in a hue. >= 5.4:1 on --ground AND
                             >= 4.85:1 on that hue's own wash. Never set body
                             copy in a DEEP tone — several fail AA on a wash.
      --w-<hue>   WASH       section grounds. Lets grounds step through the
                             rotation without any hue exceeding its budget.   */
:root{
  --c-coral:#FFA79A;      --d-coral:#BE3A2E;      --t-coral:#B8392E;      --w-coral:#FFE7DF;
  --c-peach:#FFC48C;      --d-peach:#A85812;      --t-peach:#9D5314;      --w-peach:#FFEDDC;
  --c-butter:#EFCB55;     --d-butter:#8A6B12;     --t-butter:#806315;     --w-butter:#FBEFCF;
  --c-lime:#C4D877;       --d-lime:#5E7A18;       --t-lime:#576F1B;       --w-lime:#F2F2D7;
  --c-mint:#96DFAE;       --d-mint:#1F7A46;       --t-mint:#1F7445;       --w-mint:#E8F3E3;
  --c-aqua:#84D6D3;       --d-aqua:#0F7176;       --t-aqua:#0F7176;       --w-aqua:#E4F1EB;
  --c-sky:#96CFF2;        --d-sky:#1D6FA8;        --t-sky:#1D6AA1;        --w-sky:#E8F0F2;
  --c-peri:#B4B8F4;       --d-peri:#4A4FC4;       --t-peri:#4A4FC4;       --w-peri:#EEEBF2;
  --c-lilac:#D2B2EE;      --d-lilac:#7B3FB0;      --t-lilac:#7B3FB0;      --w-lilac:#F5E9F1;
  --c-bubble:#F9AAD4;     --d-bubble:#C42D82;     --t-bubble:#B72C7B;     --w-bubble:#FEE8EB;

  /* --------------------------------- 03 Neutrals, ink, weights, shadows --- */
  --ground:#FFF9F2;       /* warm off-white page ground — 70%+ of every screen */
  --ground-2:#FDF1E4;     /* alternating band, palette body                    */
  --ground-3:#F6EEE1;     /* wells, image mats, placeholder                    */
  --card:#FFFFFF;         /* sticker faces, photo tiles                        */
  --ink:#332B42;          /* THE only outline/rule/glyph colour. 12.83:1       */
  --ink-soft:#5C5270;     /* secondary copy, lede — 6.94:1                     */
  --ink-faint:#6B6280;    /* captions, meta — 5.45:1 (floor value)             */
  --deep-bg:#2A2136;      /* dark bands + footer; cream on it = 14.67:1        */
  --hairline:#E4D9CB;     /* 1.5px dashed rules, sticker-sheet perforation     */

  /* Line weights — a fixed scale. Nothing else. */
  --lw-ui:2.5px;          /* UI borders, chips, buttons        */
  --lw-illo:3px;          /* cards, illustration strokes       */
  --lw-hair:1.5px;        /* dotted/dashed internal rules      */

  /* Radii */
  --r-xs:8px; --r-sm:14px; --r-md:20px; --r-lg:28px; --r-xl:40px; --r-pill:999px;

  /* Shadows — hard offsets, never a blur on decoration. */
  --sh-chip:0 3px 0 var(--ink);
  --sh-chip-lift:0 5px 0 var(--ink);
  --sh-sticker:0 5px 0 var(--ink);
  --sh-sticker-lift:0 11px 0 var(--ink);
  --sh-paper:0 10px 0 -4px rgba(51,43,66,.10), 0 18px 34px -18px rgba(51,43,66,.30);
  --sh-soft:0 14px 30px -18px rgba(51,43,66,.38);

  /* Spacing scale */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px;
  --sp-7:48px; --sp-8:64px; --sp-9:96px; --sp-10:128px;

  /* Measure + rhythm */
  --measure:66ch; --measure-lede:58ch;
  --wrap:1200px; --wrap-wide:1400px; --wrap-narrow:820px;
  --gut:clamp(16px,4vw,40px);

  /* Type scale (~1.25) */
  --fs-xs:.75rem; --fs-sm:.86rem; --fs-base:1.0625rem; --fs-md:1.2rem;
  --fs-lg:1.5rem; --fs-xl:1.9rem; --fs-2xl:2.6rem;
  --fs-hero:clamp(2.4rem,7vw,4.4rem);
  --fs-h2:clamp(1.65rem,3.4vw,2.4rem);

  --font-display:'Fredoka',"Trebuchet MS",Verdana,sans-serif;
  --font-serif:'Fraunces',"Iowan Old Style","Palatino Linotype",Georgia,serif;
  --font-body:'Nunito',"Trebuchet MS",-apple-system,"Segoe UI",system-ui,sans-serif;

  /* Motion */
  --ease-spring:cubic-bezier(.34,1.45,.64,1);
  --ease-out:cubic-bezier(.22,.61,.36,1);
  --dur-fast:140ms; --dur:200ms; --dur-slow:300ms;

  /* --nav-min is the bar's floor and is CONSUMED by .fable-nav__inner.
     --nav-h is the bar's real measured height, published by shared.js and
     consumed only by scroll-padding-top (and by pages that need the offset).
     Keep them separate: feeding a measured height back into min-height makes
     the bar grow on every resize tick. The values below are the correct
     static fallbacks for a no-JS / pre-paint render. */
  --nav-min:64px;
  --nav-h:72px;

  /* -------------------------------------------- 04 Accent (the ONLY mover) */
  /* Every page sets a lead hue with <body data-lead-hue="sky">. The palette
     widget rewrites these four at runtime. NOTHING ELSE re-tints: the rainbow
     furniture (chip dots, badges, swatch rows, dividers, hills, confetti) is
     assigned by index and never moves, so balance survives every user choice. */
  --accent:var(--c-coral);
  --accent-deep:var(--d-coral);
  --accent-text:var(--t-coral);
  --accent-wash:var(--w-coral);
}

/* 04b — lead-hue theme hooks. Put on <body> (or <html>): data-lead-hue="lilac" */
[data-lead-hue="coral"] {--accent:var(--c-coral); --accent-deep:var(--d-coral); --accent-text:var(--t-coral); --accent-wash:var(--w-coral);}
[data-lead-hue="peach"] {--accent:var(--c-peach); --accent-deep:var(--d-peach); --accent-text:var(--t-peach); --accent-wash:var(--w-peach);}
[data-lead-hue="butter"]{--accent:var(--c-butter);--accent-deep:var(--d-butter);--accent-text:var(--t-butter);--accent-wash:var(--w-butter);}
[data-lead-hue="lime"]  {--accent:var(--c-lime);  --accent-deep:var(--d-lime);  --accent-text:var(--t-lime);  --accent-wash:var(--w-lime);}
[data-lead-hue="mint"]  {--accent:var(--c-mint);  --accent-deep:var(--d-mint);  --accent-text:var(--t-mint);  --accent-wash:var(--w-mint);}
[data-lead-hue="aqua"]  {--accent:var(--c-aqua);  --accent-deep:var(--d-aqua);  --accent-text:var(--t-aqua);  --accent-wash:var(--w-aqua);}
[data-lead-hue="sky"]   {--accent:var(--c-sky);   --accent-deep:var(--d-sky);   --accent-text:var(--t-sky);   --accent-wash:var(--w-sky);}
[data-lead-hue="peri"]  {--accent:var(--c-peri);  --accent-deep:var(--d-peri);  --accent-text:var(--t-peri);  --accent-wash:var(--w-peri);}
[data-lead-hue="lilac"] {--accent:var(--c-lilac); --accent-deep:var(--d-lilac); --accent-text:var(--t-lilac); --accent-wash:var(--w-lilac);}
[data-lead-hue="bubble"]{--accent:var(--c-bubble);--accent-deep:var(--d-bubble);--accent-text:var(--t-bubble);--accent-wash:var(--w-bubble);}
/* At <=900px the chip rail wraps onto its own row, so the bar is ~124px.
   Keep this in step with the media query in section 09. */
@media (max-width:900px){ :root{--nav-h:124px} }

/* ------------------------------------------------ 05 Reset + base elements */
*,*::before,*::after{box-sizing:border-box}
/* Author display rules (.btn is inline-flex) out-rank the UA [hidden] rule,
   so make hiding explicit. */
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%; scroll-behavior:smooth; scroll-padding-top:calc(var(--nav-h) + 16px)}
body{
  margin:0; background:var(--ground); color:var(--ink);
  font-family:var(--font-body); font-size:var(--fs-base); line-height:1.65;
  font-variant-numeric:tabular-nums; -webkit-font-smoothing:antialiased;
  overflow-x:hidden;                 /* belt-and-braces against decoration bleed */
}
/* PRODUCTION TRAP: width/height attributes on <img> without height:auto
   stretch every photo vertically. Never remove this rule. */
img{max-width:100%; height:auto; display:block}
svg{display:block}
/* ...but an icon dropped into a sentence needs to behave like a word. */
.fable-sprite{display:inline-block; vertical-align:middle}
picture{display:block}
a{color:var(--accent-text); text-decoration-thickness:2px; text-underline-offset:3px}
a:hover{text-decoration-thickness:3px}
:focus-visible{outline:3px solid var(--ink); outline-offset:3px; border-radius:4px}
/* An ink ring on --deep-bg is 1.14:1 — invisible, and WCAG 2.2 SC 2.4.11 wants
   >= 3:1 between focused and unfocused pixels. Flip the ring to cream on every
   dark ground (cream on --deep-bg is 12.3:1). Keep this rule next to the one
   above: anything that paints a dark ground must be listed here.

   TWO-TONE, and it has to be: a dark band is not uniformly dark. 06's contact
   CTA is a .btn sitting on a WHITE bento card inside .band-dark, where a lone
   cream ring measures 1.05:1 — worse than the ink ring it replaced. So the
   cream outline (3px, offset 3px) gets an ink box-shadow ring in the 0–3px gap
   beneath it. Whichever ground the ring lands on, one of the two tones clears
   3:1: cream on --deep-bg is 12.3:1, ink on a white/cream card is 12–14:1.
   The box-shadow override costs a focused element its sticker shadow for as
   long as it holds focus, and only inside dark bands — cheap, and invisible
   unless you are looking for it. */
.band-dark :focus-visible,
.fable-lightbox__figure :focus-visible,
.band-dark:focus-visible{outline-color:var(--ground); box-shadow:0 0 0 3px var(--ink)}
button{font:inherit; color:inherit}
figure{margin:0}
hr{border:0; border-top:var(--lw-hair) dashed var(--hairline); margin:var(--sp-6) 0}
::selection{background:var(--accent); color:var(--ink)}
.fable-skip{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--ink); color:var(--ground); padding:10px 16px;
  border-radius:0 0 var(--r-sm) 0; font-weight:700;
}
.fable-skip:focus{left:0}
.visually-hidden{
  position:absolute!important; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}
/* Any wide table / diagram must live in one of these or it overflows mobile. */
.fable-scroll-x{overflow-x:auto; -webkit-overflow-scrolling:touch}
.fable-scroll-x > table{min-width:560px}

/* --------------------------------------------------------- 06 Typography */
h1,h2,h3,h4{font-family:var(--font-display); font-weight:600; line-height:1.08; margin:0 0 .4em; letter-spacing:-.015em}
h1{font-size:var(--fs-hero); line-height:1.03; letter-spacing:-.02em}
h2{font-size:var(--fs-h2)}
h3{font-size:var(--fs-md)}
h4{font-size:var(--fs-base); letter-spacing:0}
p{margin:0 0 1em; max-width:var(--measure)}
.lede{font-size:var(--fs-md); line-height:1.62; color:var(--ink-soft); max-width:var(--measure-lede)}
.caption,figcaption{font-size:var(--fs-sm); color:var(--ink-faint); line-height:1.5}
.small{font-size:var(--fs-sm)}
strong,b{font-weight:800}

/* Serif display — for the quieter samples (plate room, folio, trail).
   Fraunces at 500–600 reads storybook; 700 reads broadsheet, so stop at 600. */
.serif{font-family:var(--font-serif); font-variation-settings:"SOFT" 60,"WONK" 1; font-weight:600; letter-spacing:-.01em}
.serif-light{font-family:var(--font-serif); font-variation-settings:"SOFT" 60,"WONK" 1; font-weight:400}
/* Museum-ish plate number, tabular. */
.plate-no{font-family:var(--font-serif); font-weight:500; font-size:var(--fs-sm);
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink-faint); font-variant-numeric:tabular-nums}

/* Eyebrow: uppercase label preceded by a small flower or ringed dot. */
.eyebrow{
  display:inline-flex; align-items:center; gap:8px;
  font-family:var(--font-display); font-weight:500; font-size:var(--fs-xs);
  letter-spacing:.18em; text-transform:uppercase; color:var(--ink);
  background:var(--card); border:var(--lw-ui) solid var(--ink);
  border-radius:var(--r-pill); padding:6px 14px 6px 10px; box-shadow:var(--sh-chip);
}
.eyebrow .fable-bloom{flex:none}

/* --------------------------------------- 07 Layout, bands, rules, scenery */
.wrap{width:100%; max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gut)}
.wrap-wide{max-width:var(--wrap-wide)}
.wrap-narrow{max-width:var(--wrap-narrow)}
.section{padding-block:clamp(48px,7vw,96px)}
.section-tight{padding-block:clamp(32px,4.5vw,56px)}
.band{background:var(--ground-2)}
.band-wash{background:var(--accent-wash)}
.band-dark{background:var(--deep-bg); color:var(--ground)}
.band-dark h1,.band-dark h2,.band-dark h3{color:var(--ground)}
.band-dark .caption,.band-dark .lede{color:#D8CFE2}
.band-dark a:not(.fable-switcher__card){color:var(--c-butter)}

/* Rainbow rule — a full-width divider made of all ten hues in wheel order.
   Cheapest way to satisfy "every page shows all hues". */
.rainbow-rule{
  height:10px; border:0; margin:0; border-radius:var(--r-pill);
  background:linear-gradient(90deg,
    var(--c-coral) 0 10%, var(--c-peach) 10% 20%, var(--c-butter) 20% 30%,
    var(--c-lime) 30% 40%, var(--c-mint) 40% 50%, var(--c-aqua) 50% 60%,
    var(--c-sky) 60% 70%, var(--c-peri) 70% 80%, var(--c-lilac) 80% 90%,
    var(--c-bubble) 90% 100%);
  box-shadow:inset 0 0 0 var(--lw-ui) var(--ink);
}
.rainbow-rule.is-thin{height:6px; box-shadow:inset 0 0 0 var(--lw-hair) var(--ink)}
/* Dotted / dashed sticker-sheet perforation */
.perf-rule{border-top:var(--lw-hair) dashed var(--hairline)}

/* Rolling hills — a full-bleed scenery band. Reserve it for 2–3 samples so
   all ten do not open the same way. Markup produced by FableScenery.hills(). */
.fable-hills{display:block; width:100%; height:clamp(80px,12vw,170px)}
.fable-hills svg{width:100%; height:100%}
/* Scalloped cut-paper edge (garden-storybook). Same rule: use sparingly. */
.fable-scallop{display:block; width:100%; height:14px}

/* ----------------------------------- 08 Buttons, chips, pills and badges */
.btn{
  display:inline-flex; align-items:center; gap:9px; cursor:pointer;
  font-family:var(--font-display); font-weight:500; font-size:var(--fs-sm);
  padding:11px 20px; border-radius:var(--r-pill);
  border:var(--lw-ui) solid var(--ink); background:var(--card); color:var(--ink);
  box-shadow:var(--sh-chip); text-decoration:none;
  transition:transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.btn:hover{transform:translateY(-2px); box-shadow:var(--sh-chip-lift)}
.btn:active{transform:translateY(2px); box-shadow:0 1px 0 var(--ink)}
.btn-accent{background:var(--accent)}
.btn-ink{background:var(--ink); color:var(--ground); box-shadow:0 3px 0 rgba(51,43,66,.35)}
.btn-ink:hover{box-shadow:0 5px 0 rgba(51,43,66,.35)}

.pill{
  display:inline-flex; align-items:center; gap:7px;
  font-family:var(--font-display); font-weight:500; font-size:var(--fs-xs);
  letter-spacing:.06em; padding:5px 12px; border-radius:var(--r-pill);
  border:var(--lw-ui) solid var(--ink); background:var(--card); color:var(--ink);
}
.pill-dot{width:9px; height:9px; border-radius:50%; border:1.5px solid var(--ink); flex:none}
.tag{
  display:inline-block; font-size:var(--fs-xs); font-weight:700; letter-spacing:.04em;
  padding:4px 10px; border-radius:var(--r-pill);
  border:2px solid var(--ink); background:var(--card); color:var(--ink);
}

/* ----------------------------------------------------------- 09 Navbar */
/* Injected as the first child of <body> by shared.js. Never hand-write it. */
/* The documented mount point. `display:contents` is LOAD-BEARING: without it
   the wrapper div is exactly as tall as the bar, position:sticky has zero
   travel inside it, and the navbar scrolls away on every page. */
#fable-nav{display:contents}
/* `display:contents` still generates ::before, and :empty stops matching the
   moment shared.js appends the nav — so this reserves the bar's height for the
   one frame before the deferred script runs, then vanishes. Doing it with
   `display:block; min-height:…` instead would make the mount the sticky
   containing block and the bar would scroll away (see the note above). */
#fable-nav:empty::before{content:""; display:block; height:calc(var(--nav-min) + 21px)}
@media (max-width:900px){#fable-nav:empty::before{height:calc(var(--nav-min) + 60px)}}
.fable-nav{
  position:sticky; top:0; z-index:60;
  background:var(--card); border-bottom:var(--lw-illo) solid var(--ink);
}
.fable-nav__inner{
  display:flex; align-items:center; gap:var(--sp-4);
  max-width:var(--wrap-wide); margin-inline:auto;
  padding:9px var(--gut); min-height:var(--nav-min);
}
.fable-brand{
  display:flex; align-items:center; gap:10px; flex:none;
  text-decoration:none; color:var(--ink);
}
.fable-brand__mark{width:40px; height:40px; flex:none}
.fable-brand__name{font-family:var(--font-display); font-weight:600; font-size:1.16rem; line-height:1}
.fable-brand__sub{
  display:block; font-size:.6rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-faint); font-weight:700; margin-top:3px;
}
.fable-nav__label{
  flex:none; font-size:var(--fs-xs); color:var(--ink-faint); font-weight:700;
  letter-spacing:.1em; text-transform:uppercase; white-space:nowrap;
}
.fable-nav__right{display:flex; align-items:center; gap:10px; margin-left:auto; min-width:0; flex:1; justify-content:flex-end}

/* "All 10" hub pill — pinned, never scrolls away. */
.fable-hub{
  flex:none; background:var(--card);
  font-size:var(--fs-xs); padding:8px 14px;
}
/* The butter fill is reserved for the hub page itself. Away from the hub the
   pill sits one gap from chip 4 (butter) and two identical yellow pills read as
   one control — see 04-plate-room at 390px. Neutral here, butter below. */
.fable-hub[aria-current="page"]{background:var(--c-butter)}
/* On the hub itself the pill is the current page: same double ring the chips
   use, so the state is fill AND ring AND aria-current, never announced-only. */
.fable-hub[aria-current="page"]{
  box-shadow:0 0 0 3px var(--card), 0 0 0 6px var(--d-butter), var(--sh-chip);
}
/* The chip rail */
/* A real <ul> of <li> links (built by shared.js) — the chips must keep their
   link semantics, so no role overrides. `display:contents` on the li leaves
   the flex/scroll layout exactly as it was. */
.fable-rail{
  display:flex; gap:7px; align-items:center; overflow-x:auto; min-width:0;
  margin:0; padding:6px 2px 8px; list-style:none;
  scrollbar-width:none; overscroll-behavior-x:contain;
}
.fable-rail > li{display:contents}
/* The fade only appears when the rail really does scroll, and it points at the
   chips you cannot see yet: right fade at the start, both in the middle, left
   fade at the end. Classes set by shared.js on scroll + resize. */
.fable-rail.is-scrollable.at-start{
  -webkit-mask-image:linear-gradient(90deg,#000 0, #000 88%, transparent 100%);
          mask-image:linear-gradient(90deg,#000 0, #000 88%, transparent 100%);
}
.fable-rail.is-scrollable.at-middle{
  -webkit-mask-image:linear-gradient(90deg,transparent 0, #000 6%, #000 94%, transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0, #000 6%, #000 94%, transparent 100%);
}
.fable-rail.is-scrollable.at-end{
  -webkit-mask-image:linear-gradient(90deg,transparent 0, #000 12%, #000 100%);
          mask-image:linear-gradient(90deg,transparent 0, #000 12%, #000 100%);
}
.fable-rail::-webkit-scrollbar{display:none}
.fable-chip{
  display:inline-flex; align-items:center; gap:5px; flex:none;
  text-decoration:none; color:var(--ink); background:var(--card);
  border:var(--lw-ui) solid var(--ink); border-radius:var(--r-pill);
  padding:5px 9px; min-height:36px; box-shadow:var(--sh-chip);
  font-family:var(--font-display); font-weight:600; font-size:.9rem; line-height:1;
  transition:transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), background-color var(--dur-fast) linear;
}
.fable-chip__dot{width:9px; height:9px; border-radius:50%; border:1.5px solid var(--ink); flex:none}
.fable-chip__n{font-variant-numeric:tabular-nums}
.fable-chip__name{display:none; font-weight:500; font-size:.8rem; letter-spacing:.01em; white-space:nowrap}
.fable-chip:hover{transform:translateY(-2px); box-shadow:var(--sh-chip-lift)}
/* Active: fill AND double ring AND aria-current. Never colour alone. */
.fable-chip[aria-current="page"]{
  background:var(--accent);
  box-shadow:0 0 0 3px var(--card), 0 0 0 6px var(--accent-deep), var(--sh-chip);
}
.fable-chip[aria-current="page"] .fable-chip__name{display:inline; font-weight:700}
@media (min-width:1320px){ .fable-chip__name{display:inline} }
@media (max-width:900px){
  .fable-nav__inner{flex-wrap:wrap; gap:8px; padding-bottom:2px}
  .fable-nav__label{display:none}
  .fable-nav__right{width:100%; flex-basis:100%; margin-left:0; justify-content:flex-start}
  /* Thumbs: keep the chips at least 40px tall. About five chips are visible at
     390px (574px of rail in 286px of viewport), which is what makes the rail
     read as scrollable. The short name stays hidden here — it is on the active
     chip, in aria-label and in title — because showing it on all ten drops the
     visible count to three and makes the rail worse, not better. */
  .fable-chip{padding:6px 10px; gap:5px; font-size:.88rem; min-height:40px}
}

/* ------------------------------------- 10 Cards, photo tiles, swatch rows */
.card{
  background:var(--card); border:var(--lw-illo) solid var(--ink);
  border-radius:var(--r-lg); box-shadow:var(--sh-sticker);
  overflow:hidden; position:relative;
}
/* .sticker-corner hangs OUTSIDE the card on purpose; clipping it would
   silently delete the decoration. Documented in DESIGN.md section 8. */
.card:has(.sticker-corner){overflow:visible}
.card-flat{box-shadow:none}
.card-paper{border-width:var(--lw-ui); box-shadow:var(--sh-paper)}

/* A photo tile: mat + image + caption block. Nothing decorative may sit
   ON the photograph — badges live on the mat, corner flowers hang off the
   card's edge onto the page ground. */
.tile{display:flex; flex-direction:column; background:var(--card);
  border:var(--lw-illo) solid var(--ink); border-radius:var(--r-lg);
  box-shadow:var(--sh-sticker); position:relative;
  transition:transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease-spring);
}
.tile:hover,.tile:focus-within{transform:translateY(-6px) rotate(-1deg); box-shadow:var(--sh-sticker-lift)}
.tile:nth-child(even):hover,.tile:nth-child(even):focus-within{transform:translateY(-6px) rotate(1deg)}
/* Top padding is reserved for .tile__badge, which sits ON THE MAT — never
   over the subject. Use .tile__mat.no-badge to reclaim the room. */
.tile__mat{position:relative; padding:44px 10px 0}
.tile__mat.no-badge{padding-top:10px}
.tile__shot{
  display:block; width:100%; padding:0; border:0; background:var(--ground-3);
  border-radius:var(--r-md); overflow:hidden; cursor:zoom-in; position:relative;
}
.tile__shot picture{display:block; width:100%; height:100%}
.tile__shot img{width:100%; height:100%; object-fit:cover; object-position:var(--crop,center)}
/* Fixed-ratio variants for even grids. Omit them to let the photo keep its
   own aspect (masonry, plate grid, folio). */
.tile__shot.is-fixed{aspect-ratio:4/5}
.tile__shot.is-square{aspect-ratio:1/1}
.tile__shot.is-wide{aspect-ratio:3/2}
.tile__shot.is-tall{aspect-ratio:2/3}
.tile__shot.is-auto img{height:auto}
.tile__badge{
  position:absolute; left:14px; top:9px; z-index:2;
  font-family:var(--font-display); font-weight:500; font-size:.68rem;
  letter-spacing:.12em; text-transform:uppercase;
  padding:5px 11px; border-radius:var(--r-pill);
  border:2px solid var(--ink); background:var(--card); color:var(--ink);
  box-shadow:0 2px 0 var(--ink);
}
.tile__body{padding:14px 16px 16px; display:flex; flex-direction:column; gap:7px}
.tile__title{font-family:var(--font-display); font-weight:600; font-size:1.1rem; line-height:1.2; margin:0}
.tile__desc{margin:0; font-size:var(--fs-sm); color:var(--ink-soft); line-height:1.5; max-width:none}

/* Grids */
.grid{display:grid; gap:var(--sp-5); grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.grid-2{display:grid; gap:var(--sp-5); grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
.masonry{columns:3 260px; column-gap:var(--sp-5)}
.masonry > *{break-inside:avoid; margin-bottom:var(--sp-5)}

/* Per-artwork six-swatch signature row. Colours come from catalog.json
   `palette` — NEVER manifest `dominantColors` (background-heavy, skews grey).
   Artwork colour is quarantined: it may live here, on the card's hover border
   and in the lightbox, but never in page chrome — except through the palette
   widget, which is an explicit user act. */
.swatches{display:flex; gap:6px; align-items:center; flex-wrap:wrap; padding:0; margin:0; list-style:none}
.swatch{
  width:20px; height:20px; border-radius:50%; border:2px solid var(--ink);
  padding:0; cursor:pointer; flex:none; background:var(--sw,#fff);
  transition:transform var(--dur-fast) var(--ease-spring);
}
.swatch:hover{transform:scale(1.16)}
.swatches-lg .swatch{width:34px; height:34px; border-width:2.5px}

/* Keepsake before/after pair — a first-class pattern. */
.pair{display:grid; grid-template-columns:1fr auto 1fr; gap:var(--sp-4); align-items:center}
.pair__arrow{display:grid; place-items:center; width:64px}
.pair__note{grid-column:1/-1; font-size:var(--fs-sm); color:var(--ink-soft); max-width:74ch; margin:0 auto}
.pair__strip{grid-column:1/-1; display:flex; justify-content:center}
@media (max-width:760px){
  .pair{grid-template-columns:1fr}
  .pair__arrow{width:100%; transform:rotate(90deg)}
}

/* ------------------------------------ 11 Flower + sticker decorations */
.fable-bloom{display:inline-block; flex:none; line-height:0}
.fable-bloom svg{width:100%; height:100%; overflow:visible}
.bloom-14{width:14px;height:14px}.bloom-20{width:20px;height:20px}
.bloom-28{width:28px;height:28px}.bloom-40{width:40px;height:40px}
.bloom-64{width:64px;height:64px}.bloom-96{width:96px;height:96px}
.bloom-140{width:140px;height:140px}

/* Bob — hero flowers only, above the fold, never beside running text. */
@keyframes fable-bob{0%,100%{transform:translateY(0) rotate(0)}50%{transform:translateY(-7px) rotate(4deg)}}
.bloom-bob{animation:fable-bob 5.6s var(--ease-out) infinite}
.bloom-bob:nth-of-type(2n){animation-duration:6.4s; animation-delay:-1.4s}
.bloom-bob:nth-of-type(3n){animation-duration:5s; animation-delay:-2.6s}

/* Decorative sprinkle layer written by FableFlowers.sprinkle(). Its parent
   must be position:relative + overflow:hidden, and must not contain running
   body text at mobile widths. */
.fable-sprinkle{position:absolute; inset:0; pointer-events:none; z-index:0; overflow:hidden}
/* At phone widths the "edge bands" still cross the reading column, so the
   scatter is hidden unless the container is explicitly text-free. */
@media (max-width:760px){
  .fable-sprinkle{display:none}
  [data-sprinkle-mobile] .fable-sprinkle{display:block}
}
.fable-sprinkle > *{position:absolute}
.fable-sprinkle + *{position:relative; z-index:1}

/* Confetti ground: a printed pastel dot field. Fixed, so it reads as paper. */
.confetti{position:fixed; inset:0; pointer-events:none; z-index:0; opacity:.55;
  background-image:
    radial-gradient(circle 4px at 30px 40px, var(--c-coral) 99%, transparent),
    radial-gradient(circle 3px at 130px 22px, var(--c-butter) 99%, transparent),
    radial-gradient(circle 4px at 210px 96px, var(--c-mint) 99%, transparent),
    radial-gradient(circle 3px at 86px 150px, var(--c-sky) 99%, transparent),
    radial-gradient(circle 4px at 268px 190px, var(--c-lilac) 99%, transparent),
    radial-gradient(circle 3px at 176px 250px, var(--c-bubble) 99%, transparent),
    radial-gradient(circle 4px at 24px 250px, var(--c-peri) 99%, transparent),
    radial-gradient(circle 3px at 300px 130px, var(--c-aqua) 99%, transparent);
  background-size:340px 300px;
}
.confetti + *{position:relative}

/* Corner sticker: hangs off a card corner onto the page ground. It must never
   overlap the photograph — offset it outside the card, not over the image. */
.sticker-corner{position:absolute; right:-18px; bottom:-18px; z-index:3; pointer-events:none}
/* At phone widths the gutter is only 16px, and .tile's hover/focus tilt swings
   the corner a further ~7px, so an 18px overhang pushes the page wide. Pull it
   in — it still hangs off the card edge, which is the whole point. */
@media (max-width:760px){ .sticker-corner{right:-7px; bottom:-7px} }
/* ±1° resting tilt for scattered / sticker-sheet layouts */
.tilt-a{transform:rotate(-1.4deg)} .tilt-b{transform:rotate(1.2deg)} .tilt-c{transform:rotate(-.6deg)}

/* -------------------------------------------- 12 Artist palette widget */
.fable-palette{font-family:var(--font-body)}
.fable-palette__svg{width:100%; height:auto; max-width:440px; margin-inline:auto; overflow:visible}
.fable-blob{cursor:pointer; transform-box:fill-box; transform-origin:center;
  transition:transform 180ms var(--ease-spring)}
.fable-blob:hover,.fable-blob:focus-visible{transform:scale(1.1)}
.fable-blob[aria-pressed="true"]{transform:scale(1.16)}
.fable-blob:focus-visible{outline:3px solid var(--ink); outline-offset:2px}
/* Pointer-opened popover autofocuses the first blob; suppress the UA amber
   ring in that case so only the kit's ink ring is ever seen. */
.fable-blob:focus:not(:focus-visible){outline:none}
.fable-mixing{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap; justify-content:center;
  margin-top:var(--sp-4); font-size:var(--fs-sm); color:var(--ink-soft);
}
.fable-mixing__label{font-size:var(--fs-xs); letter-spacing:.16em; text-transform:uppercase; font-weight:800; color:var(--ink-faint)}
.fable-mixing__name{font-family:var(--font-display); font-weight:600; color:var(--ink); font-size:var(--fs-base)}
.fable-mixing__hex{font-variant-numeric:tabular-nums; letter-spacing:.02em; font-size:var(--fs-sm)}
.fable-palette__actions{display:flex; gap:10px; justify-content:center; margin-top:var(--sp-3); flex-wrap:wrap}

/* Floating launcher + popover (present on every sample page) */
.fable-palette-fab{
  position:fixed; right:18px; bottom:18px; z-index:70;
  width:56px; height:56px; border-radius:50%; display:grid; place-items:center;
  background:var(--card); border:var(--lw-illo) solid var(--ink);
  box-shadow:var(--sh-chip-lift); cursor:pointer;
}
.fable-palette-fab:hover{transform:translateY(-2px)}
/* At 390px the 56px launcher parks on top of body copy and link tails. Shrink
   it (still over the 44px touch-target floor) and tuck it into the corner. */
@media (max-width:430px){
  .fable-palette-fab{width:46px; height:46px; right:10px; bottom:10px}
  .fable-palette-fab > svg{width:28px; height:28px}
  .fable-palette-pop{right:10px; bottom:64px; width:min(380px,calc(100vw - 20px))}
}
.fable-palette-pop{
  position:fixed; right:18px; bottom:86px; z-index:71; width:min(380px,calc(100vw - 36px));
  background:var(--ground-2); border:var(--lw-illo) solid var(--ink);
  border-radius:var(--r-lg); box-shadow:var(--sh-sticker), var(--sh-soft);
  padding:var(--sp-5) var(--sp-4) var(--sp-4);
}
.fable-palette-pop[hidden]{display:none}
.fable-palette-pop__title{
  font-family:var(--font-display); font-weight:600; font-size:var(--fs-base);
  margin:0 0 4px; text-align:center;
}
.fable-palette-pop__hint{margin:0 0 var(--sp-3); text-align:center; font-size:var(--fs-xs); color:var(--ink-faint); max-width:none}
.fable-toast{
  position:fixed; left:50%; bottom:24px; transform:translateX(-50%); z-index:90;
  background:var(--ink); color:var(--ground); padding:10px 18px; border-radius:var(--r-pill);
  font-size:var(--fs-sm); font-weight:700; box-shadow:var(--sh-soft);
  max-width:calc(100vw - 116px); text-align:center;
}
.fable-toast[hidden]{display:none}
/* Hosted inside the open <dialog> (see toast() — the top layer sits above
   every z-index), so move it clear of the sticky Previous / Next row. */
.fable-lightbox .fable-toast{top:14px; bottom:auto; max-width:calc(100vw - 140px)}

/* -------------------------------------------------------- 13 Lightbox */
.fable-lightbox{
  border:0; padding:0; background:transparent; color:var(--ink);
  width:min(1120px,94vw); max-width:94vw; max-height:92vh; margin:auto;
}
.fable-lightbox::backdrop{background:rgba(42,33,54,.93)}
.fable-lightbox__panel{
  background:var(--ground); border:var(--lw-illo) solid var(--ink);
  border-radius:var(--r-lg); box-shadow:0 0 0 6px rgba(255,249,242,.10);
  display:grid; grid-template-columns:minmax(0,1.35fr) minmax(280px,.85fr);
  overflow:hidden; max-height:92vh; position:relative;
}
.fable-lightbox__figure{background:var(--deep-bg); display:grid; place-items:center; min-height:0; padding:14px}
.fable-lightbox__figure img{max-height:calc(92vh - 30px); width:auto; max-width:100%; border-radius:var(--r-sm)}
/* The right gutter is reserved for the 44px corner ✕ so a long collection
   name or title can never run under it; the two full-width rows are pulled
   back out again. */
.fable-lightbox__meta{
  padding:var(--sp-5) calc(var(--sp-5) + 44px) var(--sp-5) var(--sp-5);
  overflow-y:auto; display:flex; flex-direction:column; gap:12px;
}
.fable-lightbox__meta > .swatches,
.fable-lightbox__meta > .fable-lightbox__nav{margin-right:-44px}
.fable-lightbox__title{font-family:var(--font-display); font-weight:600; font-size:1.5rem; margin:0; line-height:1.15}
.fable-lightbox__desc{margin:0; font-size:var(--fs-sm); color:var(--ink-soft); line-height:1.6; max-width:none}
.fable-lightbox__swatch-label{font-size:var(--fs-xs); letter-spacing:.14em; text-transform:uppercase; color:var(--ink-faint); font-weight:800; margin:0}
.fable-lightbox__nav{display:flex; gap:10px; align-items:center; margin-top:auto; padding-top:var(--sp-3); flex-wrap:wrap}
.fable-lightbox__close{
  position:absolute; right:12px; top:12px; z-index:5;
  width:44px; height:44px; padding:0; display:grid; place-items:center;
  border-radius:50%; background:var(--ground); color:var(--ink);
  border:var(--lw-ui) solid var(--ink); box-shadow:var(--sh-chip); cursor:pointer;
  font-family:var(--font-display); font-size:1.15rem; line-height:1;
}
.fable-lightbox__close:hover{transform:translateY(-2px)}
.fable-lightbox__counter{font-size:var(--fs-xs); color:var(--ink-faint); font-weight:700; letter-spacing:.08em}
/* the invitation under a piece (trigger carries data-lightbox-cta="Words|/link/|style|line") */
.fable-lightbox__invite{margin-top:auto; display:flex; flex-direction:column; align-items:flex-start; gap:10px}
.fable-lightbox__invite[hidden]{display:none}
.fable-lightbox__invite:not([hidden]) + .fable-lightbox__nav{margin-top:var(--sp-3)}
.fable-lightbox__cta-note{margin:0; font-size:var(--fs-sm); color:var(--ink-soft); line-height:1.5; max-width:none}
.fable-lightbox__cta-note[hidden]{display:none}
/* 2 · a line, then an ink button */
.fable-lightbox--cta-2 .fable-lightbox__cta{background:var(--ink); color:var(--ground); box-shadow:0 3px 0 rgba(51,43,66,.35)}
/* 3 · an italic line, as a link */
.fable-lightbox--cta-3 .fable-lightbox__cta{background:none; border:0; box-shadow:none; padding:0; font-family:'Fraunces',Georgia,serif; font-style:italic; font-weight:400; font-variation-settings:'SOFT' 100,'WONK' 1,'opsz' 48; font-size:1.25rem; color:var(--ink); text-decoration:underline; text-decoration-thickness:1.5px; text-underline-offset:5px}
.fable-lightbox--cta-3 .fable-lightbox__cta:hover{transform:none; text-decoration-thickness:2.5px}
/* 4 · a little card: a bloom, a heading, the button */
.fable-lightbox--cta-4 .fable-lightbox__invite{background:var(--ground-2); border:2px solid var(--ink); border-radius:16px; padding:14px 16px 16px; align-self:stretch; align-items:flex-start}
.fable-lightbox--cta-4 .fable-lightbox__cta-note{font-family:'Fraunces',Georgia,serif; font-style:italic; font-weight:400; font-variation-settings:'SOFT' 100,'WONK' 1,'opsz' 48; font-size:1.35rem; color:var(--ink); line-height:1.15; padding-left:30px; position:relative}
.fable-lightbox--cta-4 .fable-lightbox__cta-note::before{content:"✿"; position:absolute; left:0; top:0; color:var(--c-coral)}
/* 5 · a white pill with a bloom, full width */
.fable-lightbox--cta-5 .fable-lightbox__cta{background:var(--card); align-self:stretch; justify-content:center; text-align:center}
.fable-lightbox--cta-5 .fable-lightbox__cta::before{content:"✿"; color:var(--c-coral); margin-right:8px}
/* a bare viewer (trigger carries data-lightbox-bare): the photograph, the counter and the buttons only */
.fable-lightbox--bare .fable-lightbox__title,.fable-lightbox--bare .fable-lightbox__desc,.fable-lightbox--bare .fable-lightbox__swatch-label,.fable-lightbox--bare .swatches,.fable-lightbox--bare .caption{display:none}
/* a plain viewer (trigger carries data-lightbox-plain): the photograph, the name and the size only */
.fable-lightbox--plain .fable-lightbox__swatch-label,.fable-lightbox--plain .swatches,.fable-lightbox--plain .caption{display:none}
@media (max-width:860px){
  .fable-lightbox__panel{grid-template-columns:1fr; grid-template-rows:auto minmax(0,1fr)}
  /* The ✕ sits over the figure here, not the meta pane — reclaim the gutter. */
  .fable-lightbox__meta{padding-right:var(--sp-5)}
  .fable-lightbox__meta > .swatches,
  .fable-lightbox__meta > .fable-lightbox__nav{margin-right:0}
  .fable-lightbox__figure img{max-height:38vh}
  /* Previous / Next are the primary action here — pin them to the bottom of
     the scrolling meta pane instead of letting them fall below the fold. */
  .fable-lightbox__nav{
    position:sticky; bottom:0; margin-top:var(--sp-3);
    padding-block:var(--sp-3); background:var(--ground);
    box-shadow:0 -1px 0 var(--hairline);
  }
}
/* Lock the y-axis ONLY. Setting `overflow:hidden` here and then removing it
   makes Chromium stop honouring body's own `overflow-x:hidden` afterwards,
   and any decoration that hangs off a card edge (.sticker-corner) starts
   causing horizontal page scroll the moment the lightbox is closed. */
body.fable-lock{overflow-y:hidden}
body.fable-lock .fable-palette-fab,body.fable-lock .fable-palette-pop{display:none}

/* ---------------------------------------------------------- 14 Footer */
.fable-footer{background:var(--ground-2); border-top:var(--lw-illo) solid var(--ink); position:relative}
.fable-footer__inner{
  max-width:var(--wrap); margin-inline:auto; padding:var(--sp-8) var(--gut) var(--sp-6);
  display:grid; gap:var(--sp-6); grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
}
.fable-footer h3{margin-bottom:.3em}
.fable-footer__bottom{
  border-top:var(--lw-hair) dashed var(--hairline); text-align:center;
  padding:var(--sp-4) var(--gut) var(--sp-6); font-size:var(--fs-sm); color:var(--ink-faint);
}

/* --------------------------- 15 Hue rotation — balance without thinking */
/* Put .hue-rot on a container: its children take the wheel in order,
   repeating every ten. Deterministic; never Math.random(). */
.hue-rot > *:nth-child(10n+1){--hue:var(--c-coral);  --hue-deep:var(--d-coral);  --hue-wash:var(--w-coral)}
.hue-rot > *:nth-child(10n+2){--hue:var(--c-peach);  --hue-deep:var(--d-peach);  --hue-wash:var(--w-peach)}
.hue-rot > *:nth-child(10n+3){--hue:var(--c-butter); --hue-deep:var(--d-butter); --hue-wash:var(--w-butter)}
.hue-rot > *:nth-child(10n+4){--hue:var(--c-lime);   --hue-deep:var(--d-lime);   --hue-wash:var(--w-lime)}
.hue-rot > *:nth-child(10n+5){--hue:var(--c-mint);   --hue-deep:var(--d-mint);   --hue-wash:var(--w-mint)}
.hue-rot > *:nth-child(10n+6){--hue:var(--c-aqua);   --hue-deep:var(--d-aqua);   --hue-wash:var(--w-aqua)}
.hue-rot > *:nth-child(10n+7){--hue:var(--c-sky);    --hue-deep:var(--d-sky);    --hue-wash:var(--w-sky)}
.hue-rot > *:nth-child(10n+8){--hue:var(--c-peri);   --hue-deep:var(--d-peri);   --hue-wash:var(--w-peri)}
.hue-rot > *:nth-child(10n+9){--hue:var(--c-lilac);  --hue-deep:var(--d-lilac);  --hue-wash:var(--w-lilac)}
.hue-rot > *:nth-child(10n+10){--hue:var(--c-bubble);--hue-deep:var(--d-bubble); --hue-wash:var(--w-bubble)}
.hue-fill{background:var(--hue,var(--accent))}
.hue-badge{background:var(--hue,var(--accent))}
.hue-dot{background:var(--hue,var(--accent))}

/* The sample switcher — a hub/footer grid of the ten samples. Populated by
   FableSwitcher.mount(el). Each card leads with its own hue. */
.fable-switcher{display:grid; gap:var(--sp-4); grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); padding:0; margin:0; list-style:none}
.fable-switcher__card{
  display:flex; flex-direction:column; gap:8px; height:100%; text-decoration:none; color:var(--ink);
  background:var(--card); border:var(--lw-illo) solid var(--ink); border-radius:var(--r-md);
  box-shadow:var(--sh-chip); overflow:hidden;
  transition:transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease-spring);
}
.fable-switcher__card:hover{transform:translateY(-5px) rotate(-.7deg); box-shadow:var(--sh-sticker)}
.fable-switcher__band{height:38px; background:var(--hue,var(--accent)); border-bottom:var(--lw-ui) solid var(--ink); display:flex; align-items:center; justify-content:space-between; padding:0 10px}
.fable-switcher__n{font-family:var(--font-display); font-weight:600; font-size:1rem}
.fable-switcher__body{padding:0 12px 14px}
.fable-switcher__name{font-family:var(--font-display); font-weight:600; font-size:1.02rem; display:block}
.fable-switcher__note{font-size:var(--fs-xs); color:var(--ink-faint); display:block; margin-top:3px; line-height:1.45}
.fable-switcher__card[aria-current="page"]{box-shadow:0 0 0 3px var(--ground), 0 0 0 6px var(--ink), var(--sh-chip)}
/* The card face is always white and the band is always a pastel, wherever the
   grid is placed — so its text is always ink, even inside a .band-dark
   section (07 and 10 do exactly that). Belt and braces with the
   :not(.fable-switcher__card) narrowing on .band-dark a. */
.band-dark .fable-switcher__card,
.band-dark .fable-switcher__card:hover,
.band-dark .fable-switcher__name,
.band-dark .fable-switcher__n{color:var(--ink)}
.band-dark .fable-switcher__note{color:var(--ink-faint)}
/* The eleventh card — back to the hub. Cream face, rainbow band. */
.fable-switcher__card.is-hub{background:var(--ground)}
.fable-switcher__card.is-hub .fable-switcher__band{
  background:linear-gradient(90deg,
    var(--c-coral) 0 10%, var(--c-peach) 10% 20%, var(--c-butter) 20% 30%,
    var(--c-lime) 30% 40%, var(--c-mint) 40% 50%, var(--c-aqua) 50% 60%,
    var(--c-sky) 60% 70%, var(--c-peri) 70% 80%, var(--c-lilac) 80% 90%,
    var(--c-bubble) 90% 100%);
}
.fable-switcher__card.is-hub .fable-switcher__n{font-size:.78rem; letter-spacing:.12em; text-transform:uppercase; font-family:var(--font-body); font-weight:800}

/* ------------------------------------------- 16 Reduced motion + print */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important; animation-iteration-count:1!important;
    transition-duration:.001ms!important; scroll-behavior:auto!important;
  }
  html{scroll-behavior:auto}
  .tile:hover,.tile:focus-within,.fable-chip:hover,.btn:hover,
  .fable-switcher__card:hover,.swatch:hover,.fable-blob:hover{transform:none}
  .bloom-bob{animation:none}
  .fable-reveal{opacity:1!important; transform:none!important}
}
/* Scroll reveal — JS sets .is-in. Elements start visible if JS never runs. */
.fable-reveal{opacity:1}
html.js .fable-reveal{opacity:0; transform:translateY(12px);
  transition:opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out)}
html.js .fable-reveal.is-in{opacity:1; transform:none}

@media print{
  .fable-nav,.fable-palette-fab,.fable-palette-pop,.confetti,.fable-sprinkle{display:none!important}
  body{background:#fff}
  /* .fable-reveal is opacity:0 until an IntersectionObserver hit, and printing
     never scrolls — without this every below-fold section prints blank. */
  html.js .fable-reveal,.fable-reveal{opacity:1!important; transform:none!important}
}
