/* apps/cf-pages/sakeozo-site/src/site.css
   Last modified 2026-10-20 02:50 EDT by Claude (Builder desk, Step 4453.site.4, task recaRPeVAxnK8sQo9) for Destiny
   Slater: the /r4/ port's r4.css (apps/cf-pages/sakeozo-directions/src/r4/r4.css at origin/main a275e4ae, plus its fix
   round 340e977e: the still service button, .pf-grid.pf-placed and the desktop menu row), unchanged
   except the pet lists at 1024 to 1199 px (15 px there, under the 16 px floor; see its note), with one block at the end for what the day-one site adds (the footer support row, links and contact block, the feed
   slot, the Worlds index, the world pages' cast without art and coming-soon block, the FAQ page). Same tokens, no new
   colour. History of every rule above that block: git log on the /r4/ port's r4.css. */
/* File: apps/cf-pages/sakeozo-directions/src/r4/r4.css. Ported 2026-10-12 21:50 EDT by Claude (Builder desk, Step
   4550.site.2, task rec2hWgyeYbj1EIwR) from projects/sakeozo/design/site-directions-r4/src/r4.css (commit 5305392c,
   Step 4591.rev.1; spec TPR-7487 amending TPR-7454), unchanged except: the Home services row is three equal columns
   from 1280 px with 22 px headings (steer note of 8:33 PM EDT), Nap time's zzz is 16 px (the text floor), and (round 2,
   2026-10-12 21:55 EDT) the timeline's year column is 64 px below 768 px so no line holds one word. Revision 3 port
   2026-10-14 04:50 EDT, Step 4701.rev.2 (task recd42u0G1mGBjayg): the reference's 4f103040 changes, plus the port fixes
   at the end of this file (the seven-width checks, and the testimonial arrows' gutter). Revision 4 port 2026-10-15 19:40
   EDT, Step 5006.rev.2 (task rec67MZIfEbUFVxRZ): the reference's c63f63a9 changes, without the Links chooser rules
   (her pick A). Art port 2026-10-16 08:35 EDT, Step 5033.art.2 (task recu3iZbVO1VpGG4u): the reference's
   3495b8b0..00362e05 changes, unchanged; the ART section sits before the Builder port fixes. Revision 5 port
   2026-10-17 06:10 EDT, Step 5053.rev.2 (task reckkVCcfCEjD44xG): the reference's 00362e05..38324167 changes, the
   REVISION 5 section before the Builder port fixes; a port section at the end sizes her dizzy doll and spins her
   swirls (Task 5053 live-session asks). Timeline port 2026-10-17 13:30 EDT, Step 5061.tl.2 (task rec7zLqiXPDBEwr5r): the
   reference's 32363c7c TIMELINE section, unchanged, at the very end; the old timeline rules (and the port's 64 px year
   column and .tl-what fixes) removed; a port-fix block at the end for what the seven-width every-line check found at
   320, 768 and 1024 px.
   Last modified: 2026-10-20 09:00 EDT | Author: Claude (live session for Eric Belozovsky) for Destiny Slater | Three
   PORT FIXes: the Home service button keeps still inside its card (it flickered: a transformed .svc-go became the
   containing block of its own ::after cover); .pf-grid.pf-placed for site.js's stable portfolio placement; on desktop
   the open phone dropdown never out-ranks the nav row. Tests: r4-hover, r4-portfolio and r4-menu browser files.
   Before: 2026-10-19 19:20 EDT | Author: Claude (Builder desk, Step 5575.rev.2, task recNVYtOOjlB82wDw) for Destiny
   Slater | Revision 7 port (Task 5575): the reference's ec2f1739 TIMELINE section (her drawn line, year by the knot,
   pictures then words as one unit, her ending, the award and talk logo rows) and its REVISION 7 block (matcha Client
   line, testimonial pictures and excerpt marks, 404 hearts and the angry vibration, the Ko-fi widget stand-in),
   unchanged. The Step 5061.tl.2 port-fix block for the old trophy, talks and beat rules is removed with them. One port
   fix before the REVISION 7 block: --lx and --lw also on .tl-wrap, so her ending sits on the line below 1024 px; and
   one for the every-line rule: award and talk columns by measured width (1, 2, 3, 4, 5 across at <560, 560, 768,
   1024, 1200 px) and Step 5061.tl.2's two 320 px fixes (the 2024 link's glue, the shelf heading at 19 px), kept.
   Before: 2026-10-18 19:20 EDT | Step 5159.cs.2 | Case study
   port (Task 5159): the reference's fada8bc9 CASE STUDY PAGES section, unchanged, then one port fix after it (a card's
   one track is minmax(0, 1fr) below 1024 px; round 2: a study's story text is 16 px below 360 px).
   Before: 2026-10-18 13:10 EDT | Step 5146.rev.2 | Revision 6
   port (32363c7c..7d725789): .ily-img has no idle shake and ily-twitch plays once a miss; a REVISION 6 section at the very
   end, without its Part A (the port section above already sizes her dizzy doll and swirls), plus .vh and a two-line
   mad caption (TPR-9072). Designer's history: */
/* File: projects/sakeozo/design/site-directions-r4/src/r4.css 
   Last modified: 2026-10-16 17:45 EDT | Author: Claude (Designer desk, Step 5053.rev.1, task recag9crJVZ3OcFjb) |
   Revision 5 (Task 5053): a REVISION 5 section at the end (the water bucket, its splash and the status line; the
   reward; the dizzy doll; the zoomable pet pictures; the moved-page stub). Before that, Step 5033.art.1 |
   Her art and phone findings (Task 5033): an ART section at the end (her Nap time icons, her animated doll always on
   top, the 404 poses on a fixed stage and her squiggle, Nap time stops every animation and transition, testimonial
   quote first, the support row, Portfolio on a phone); the duck rule and the doll's idle bob removed above.
   Revision 4 (Task 5006): a REVISION 4 section at the end (Links backgrounds A, B and C (A redrawn as a conic diamond lattice), one hover and focus rule for
   every Links button, the avatar ring: Part A; the 404 sparkle rules removed; Part B; the napping doll, no Psst under Nap time, the lightbox hint; Part C; the splash cross-fade and the wrapping Worlds row; Part D; Hire Me tier columns and picture height, the alt text panel cap: Part E).
   Revision 3 (Task 4701): a REVISION 3 section at the end (green and pink buttons, toggles, the rail, cards, viewer, About,
   Terms, and every page from 320 px).
   Revision 2 (Task 4617): the 404 glow and "!!" replaced by white sprinkles and an S squiggle, Links as ONE layout (her
   mix) on a patterned red with the preview panel gone, her photo on About, and her two optional art pieces on About.
   Revision (Task 4591): G1 and N2 only (the G2 tokens, N1's picture strip and every data-ground="2" or data-nav="1"
   rule are gone), and a REVISION section at the end: her two testimonial breaks, the round name-sign, About's photo over
   the video and the FAQ, the Hire Me tier pictures with no outline, the guide's role boxes and ticks, smaller Back to
   top hand on one label baseline, the links page's three layouts, her menu picture buttons and the Case Studies page.
   Round 4: ONE site on R3-1. The middle part is R3-1's own sections (site-directions-r3/src/r3-1.css, revision 1) with
   every #2B0007 outline and hard shadow moved to tokens. This head sets the tokens for both grounds and both navigation
   variants; the tail adds the round 4 parts and the hover and press vocabulary (her answer 1, "go crazy").
   Backgrounds, G1: wine, wine deep, cream, paper, white, peach, matcha. Midnight #0A0024 is text only. */

/* ---------- G1, the default: R3-1's mature deep red back-background, sticker outlines, hard shadows ---------- */
:root {
  --ground: #56000E; --doodle-ink: #88A31F; --doodle-size: 480px;
  --fg: #0A0024; --muted: #0A0024; --line: #56000E; --card: #FFFFFF;
  --accent: #56000E; --accent-hover: #3F000A; --accent-fg: #FEF1DF; --link: #56000E; --focus: #56000E; --eyebrow: #56000E;
  --btn-line: var(--line); --btn2-bg: #FFFBF4; --btn2-fg: #0A0024; --btn2-line: var(--line);
  --chip-bg: #F2C0AB; --chip-fg: #0A0024; --tst-bg: #FFFFFF; --tst-fg: #0A0024; --tst-name: #56000E; --tst-role: #4B5A0F;
  --ph: #56000E; --radius: 18px;
  /* Global 8: outlines and hard shadows are Deep Wine Red. One token, --line; nothing here is #2B0007. */
  --edge: 3px solid var(--line); --edge-sm: 2px solid var(--line); --edge-dash: 3px dashed var(--line);
  --hard-xs: 3px 3px 0 var(--line); --hard-sm: 4px 4px 0 var(--line); --hard: 6px 6px 0 var(--line); --hard-lg: 8px 8px 0 var(--line);
  --lift: 9px 10px 0 var(--line); --press: 1px 1px 0 var(--line);
  --sheet-edge: 3px solid #FEF1DF; --sheet-shadow: 12px 12px 0 #88A31F; --sheet-radius: 36px;
  --hover-move: translate(-3px, -4px) rotate(-1.5deg); --press-move: translate(2px, 2px) scale(.96);
  --card-hover: translate(-4px, -7px) rotate(0deg); --card-press: translate(2px, 2px) scale(.97);
}

/* =====================================================================================================================
   R3-1, AS IT WAS (site-directions-r3/src/r3-1.css), with every outline and hard shadow on the tokens above
   ===================================================================================================================== */
.sheet { background: #FEF1DF; }
@media (min-width: 1024px) { .sheet { max-width: 1376px; margin: 32px auto; border: var(--edge); border-radius: 36px; overflow: clip; box-shadow: var(--hard-lg); } }
h1, h2, h3 { letter-spacing: -0.01em; }
.h2 { color: #56000E; }
.btn:hover { transform: translate(-2px, -2px); box-shadow: var(--hard); }

/* changing section colours (C) */
.band-cream { background: #FEF1DF; } .band-paper { background: #FFFBF4; } .band-peach { background: #F2C0AB; border-block: var(--edge); }
.band-matcha { background: #88A31F; border-block: var(--edge); } .band-matcha .h2, .band-matcha .eyebrow, .band-matcha .more { color: #0A0024; }
.band-wine { background: #56000E; color: #FEF1DF; } .band-wine .h2, .band-wine .eyebrow { color: #F2C0AB; }
.band-wine .btn-follow { --btn2-bg: #FEF1DF; }
.pet-peek li { background: #FFFFFF; border: var(--edge); border-radius: 16px; padding: 8px 8px 10px; box-shadow: var(--hard-sm); transform: rotate(var(--r)); }
.pet-peek img { border-radius: 10px; }
.pet-peek span { font-family: var(--font-hand); font-size: var(--t2); font-weight: 400; color: #56000E; }
.svc-card { border: var(--edge); box-shadow: var(--hard); background: #FFFBF4; }
.svc-card:nth-child(2) { transform: rotate(-1deg); } .svc-card:nth-child(3) { transform: rotate(1deg); }
.svc-thumbs img { border: var(--edge-sm); }
.svc-from { background: #88A31F; color: #0A0024; padding: 4px 14px; border-radius: 999px; border: var(--edge-sm); transform: rotate(-2deg); }
.world-card { background: #FFFFFF; border: var(--edge); border-radius: var(--radius); padding: 8px 8px 12px; box-shadow: var(--hard-sm); }
.world-card:nth-child(odd) { transform: rotate(-1.5deg); } .world-card:nth-child(even) { transform: rotate(1.5deg); }
.world-art { border-radius: 12px; }
.world-name { color: #56000E; } .world-cast { color: #0A0024; }
.tst { border: var(--edge); border-radius: 28px; box-shadow: var(--hard); }
.tst::after { content: ''; position: absolute; left: 96px; bottom: -20px; width: 30px; height: 30px; background: #FFFFFF; border-right: var(--edge); border-bottom: var(--edge); transform: skewX(30deg) rotate(45deg); }
.tst-grid { gap: var(--sp6) var(--sp5); }
.feed-tile { border: var(--edge); }
.feed-tile:nth-child(odd) { transform: rotate(-2deg); } .feed-tile:nth-child(even) { transform: rotate(2deg); }
.support-card { --card: #FEF1DF; border-color: var(--line); box-shadow: var(--hard-sm); color: #0A0024; }
.support-card strong { color: #56000E; }

/* about */
.about-intro { background: #88A31F; border-bottom: var(--edge); }
.about-intro .eyebrow, .about-intro .display { color: #0A0024; }
/* The timeline's rules are in the TIMELINE section at the end (Step 5061.tl.1). */
.timeline { background: #FEF1DF; }
.pets { background: #F2C0AB; border-block: var(--edge); }
.pet-card { border: var(--edge); box-shadow: var(--hard); }
.pet-grid > li:nth-child(odd) { transform: rotate(-1.2deg); } .pet-grid > li:nth-child(even) { transform: rotate(1.2deg); }
.pet-name { font-family: var(--font-hand); font-weight: 400; font-size: var(--t5); color: #56000E; }
.off { background: #FFFBF4; }
.off-art img { border: var(--edge); box-shadow: var(--hard); transform: rotate(-2deg); }
.closing { background: #88A31F; border-top: var(--edge); } .closing .h2 { color: #0A0024; }

/* portfolio, world, hire */
.pf-head { background: #F2C0AB; border-bottom: var(--edge); }
.tab { border-color: var(--line); background: #FFFBF4; }
.piece-frame { border: var(--edge); box-shadow: var(--hard-sm); background: #FFFFFF; padding: 6px; transform: rotate(var(--r)); }
.piece-frame img { border-radius: 10px; }
.world-hero { background: #56000E; }
.world-hero-art img { border-bottom: var(--edge); }
.world-hero-text { background: #F2C0AB; border: var(--edge); border-radius: var(--radius); margin: calc(-1 * var(--sp7)) var(--gutter) var(--sp5); position: relative; box-shadow: var(--hard); max-width: 820px; padding: var(--sp5); }
@media (min-width: 1024px) { .world-hero-text { margin-left: var(--sp8); } }
.cast { background: #FEF1DF; }
.cast-art { border: var(--edge); box-shadow: var(--hard); }
.world-work { background: #88A31F; border-top: var(--edge); } .world-work .h2, .world-nav a { color: #0A0024; }
.world-follow { border: var(--edge); --card: #FEF1DF; }
.hire-head { background: #88A31F; border-bottom: var(--edge); } .hire-head .eyebrow, .hire-head .display { color: #0A0024; }
.svc-jump a { background: #FFFBF4; border-color: var(--line); color: #0A0024; }
.svc-list { background: #FEF1DF; }
.svc-block + .svc-block { border-top: var(--edge-dash); }
.svc-from { display: inline-block; }
@media (max-width: 559px) { .svc-block .h2 { font-size: var(--t3); } }
.tier { border: var(--edge); box-shadow: var(--hard-sm); }
.tier-ex img { border: var(--edge-sm); }
.tier-ex img:nth-child(odd) { transform: rotate(-2deg); } .tier-ex img:nth-child(even) { transform: rotate(2deg); }
.tier-price { align-self: flex-start; background: #F2C0AB; padding: 2px 12px; border: var(--edge-sm); border-radius: 10px; transform: rotate(-2deg); color: #56000E; }
.guide { background: #FFFBF4; border-block: var(--edge); }
.fee { border: var(--edge-dash); --card: #FEF1DF; }
.inquiry { background: #F2C0AB; }

/* the intro video band on About (C9) */
.intro-vid .vid-frame { border: var(--edge); box-shadow: var(--hard); transform: rotate(-1.5deg); }

/* Revision 1 (Part B): her gecko PNG stands in front of the video, bottom right at 85% of the frame height. It takes no
   pointer events, so a click on the video still plays it. The Play/Pause button sits under the frame (.vid-bar), where
   the PNG cannot cover it. */
.has-gecko .vid-frame video { cursor: pointer; }
.gecko-over { position: absolute; right: 1%; bottom: 0; height: 85%; width: auto; max-width: none; pointer-events: none; }
.vid-bar { padding-top: var(--sp3); }
.vid-toggle { box-shadow: var(--hard-xs); }
.vid-ico { display: inline-block; width: 0; height: 0; border-left: 14px solid currentColor; border-top: 8px solid transparent; border-bottom: 8px solid transparent; margin-right: var(--sp2); }
.playing .vid-ico { width: 14px; height: 16px; border: 0; border-left: 5px solid currentColor; border-right: 5px solid currentColor; }

/* =====================================================================================================================
   ROUND 4 PARTS
   ===================================================================================================================== */
.sheet { background: #FEF1DF; }
@media (min-width: 1024px) { .sheet { border: var(--sheet-edge); box-shadow: var(--sheet-shadow); border-radius: var(--sheet-radius); overflow: clip; } }
.intro-vid .vid-frame { border: var(--edge); box-shadow: var(--hard); transform: rotate(-1.5deg); }


/* ---------- the sticky top bar (Global 5). Both variants stay sticky; N2 adds a picture beside each word ---------- */
.site-header { position: sticky; top: 0; z-index: 40; background: #FEF1DF; border-bottom: var(--edge); box-shadow: var(--hdr-shadow, none); }
.hdr { min-height: 72px; gap: var(--sp3); }
.brand { gap: var(--sp1); padding: 4px 6px; border-radius: 14px; transition: transform 300ms var(--spring); }
.brand-icon { height: 46px; width: auto; transition: transform 400ms var(--spring); }
.brand-word { height: 30px; width: auto; }
.brand:hover .brand-icon, .brand:focus-visible .brand-icon { transform: rotate(-12deg) scale(1.12); }
.brand:active { transform: scale(.94); }
.nav-list { list-style: none; margin: 0; padding: 0; display: none; }
.nav-a { display: flex; align-items: center; gap: 10px; padding: 8px 14px; min-height: 48px; border-radius: 999px; color: #0A0024; text-decoration: none;
  font: 600 var(--t0)/1.2 var(--font-display); border: 2px solid transparent;
  transition: transform 260ms var(--spring), background-color 160ms ease; }
.nav-t { background: linear-gradient(#56000E, #56000E) 0 100% / 0 3px no-repeat; transition: background-size 260ms ease; padding-bottom: 2px; }
.nav-a:hover, .nav-a:focus-visible { transform: translateY(-3px) rotate(-3deg); }
.nav-a:hover .nav-t, .nav-a:focus-visible .nav-t { background-size: 100% 3px; }
.nav-a:active { transform: translateY(1px) scale(.94); }
.nav-a[aria-current="page"] { background: #88A31F; border: var(--edge-sm); box-shadow: var(--hard-xs); }
.nav-a[aria-current="page"] .nav-t { background-size: 0 3px; }
/* N2: the picture beside each word, three states (resting, hover or focus, pressed). N1 hides it. */
.np { display: block; flex: none; width: 38px; height: 38px; border-radius: 50%; overflow: hidden; background: #FFFFFF; box-shadow: 0 0 0 3px #F2C0AB;
  transition: transform 320ms var(--spring), box-shadow 160ms ease, filter 160ms ease; }
.np img { width: 100%; height: 100%; object-fit: cover; }
.nav-a:hover .np, .nav-a:focus-visible .np { transform: scale(1.22) rotate(-10deg); box-shadow: 0 0 0 3px #88A31F; }
.nav-a:active .np { transform: scale(.88) rotate(4deg); box-shadow: 0 0 0 3px #56000E; filter: brightness(.82) saturate(1.2); }
.hdr-actions { gap: var(--sp2); }
.btn-hire { min-height: 48px; padding: 8px 18px; box-shadow: var(--hard-xs); }
.menu-btn { display: inline-flex; align-items: center; gap: 8px; border: var(--edge-sm); background: #FFFBF4; color: #0A0024; min-height: 48px; transition: transform 260ms var(--spring); }
.menu-btn:hover { transform: rotate(-3deg) translateY(-2px); } .menu-btn:active { transform: scale(.94); }
.menu-ico { display: grid; gap: 3px; } .menu-ico i { display: block; width: 18px; height: 3px; border-radius: 2px; background: #56000E; transition: transform 200ms ease; }
.menu-btn[aria-expanded="true"] .menu-ico i:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.menu-btn[aria-expanded="true"] .menu-ico i:nth-child(2) { transform: scaleX(0); }
.menu-btn[aria-expanded="true"] .menu-ico i:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
.nav-list.open { display: grid; gap: var(--sp1); position: absolute; left: 0; right: 0; top: 100%; background: #FEF1DF; padding: var(--sp3) var(--gutter) var(--sp4); border-bottom: var(--edge); box-shadow: var(--hard-sm); }
.nav-list.open .nav-a { justify-content: flex-start; }
@media (max-width: 559px) { .btn-hire { display: none; } .nap-hdr .nap-t { display: none; } .brand-word { height: 24px; } .brand-icon { height: 40px; } }
@media (min-width: 560px) { .nav-hire { display: none; } .nav-list.open .nav-hire { display: block; } }
@media (min-width: 1024px) {
  .nav-list { display: flex; gap: 2px; } .nav-hire { display: none !important; } .menu-btn { display: none; } .nav { margin-left: auto; }
  /* PORT FIX (Tuesday, October 20, 2026): the open phone dropdown never out-ranks the desktop row (it stayed drawn,
     and the button that closes it is hidden here). site.js also closes the menu when the window crosses 1024 px. */
  .nav-list.open { display: flex; position: static; padding: 0; background: none; border: 0; box-shadow: none; }
  .brand { margin-right: 0; } }
@media (min-width: 1024px) and (max-width: 1279px) { html[data-nav="2"] .nav-a { padding: 8px 10px; gap: 8px; } html[data-nav="2"] .nap-hdr .nap-t { display: none; } }


/* ---------- Nap time (her answer 4): one gecko that naps. Pauses every block that moves ---------- */
.nap { display: inline-flex; align-items: center; gap: 6px; min-height: 48px; min-width: 48px; padding: 2px 14px 2px 4px; border-radius: 999px; border: var(--edge-sm); background: #FFFBF4; color: #0A0024;
  font: 600 16px/1 var(--font-display); cursor: pointer; transition: transform 300ms var(--spring), background-color 160ms ease; }
.nap-face { position: relative; display: block; width: 44px; height: 40px; }
.gf { display: block; transition: transform 400ms var(--spring); }
.gf img { display: block; width: 42px; height: 40px; object-fit: contain; }
.gf img.gf-shut { display: none; }
.zz { position: absolute; right: -6px; top: -10px; font: 700 16px/1 var(--font-display); color: #56000E; display: none; }
.zz i { font-style: normal; display: inline-block; }
.nap:hover .gf, .nap:focus-visible .gf { transform: rotate(-14deg) scale(1.1); }
.nap:active { transform: scale(.92); }
html[data-motion="nap"] .nap { background: #F2C0AB; }
html[data-motion="nap"] .nap .gf img.gf-open { display: none; } html[data-motion="nap"] .nap .gf img.gf-shut { display: block; }
html[data-motion="nap"] .nap .zz { display: block; }
html[data-motion="nap"] .nap .gf { transform: rotate(14deg) translateY(2px); }
.nap-chip { min-height: 44px; }
.sec-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp3); }

/* ---------- Home 1: the hero. R3-1's copy on a smaller card, low and to one side, so the drawing shows ---------- */
.hero { position: relative; padding: 0; display: grid; overflow: hidden; background: #56000E; }
.hero-art { position: relative; height: 360px; }
.hero-art img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; }
.hero-wrap { position: relative; z-index: 2; margin-top: -48px; padding-bottom: var(--sp6); width: 100%; }
.hero-card { background: #FEF1DF; color: #0A0024; border: var(--edge); border-radius: 26px; box-shadow: var(--hard-lg); padding: var(--sp4) var(--sp4) var(--sp4); transform: rotate(-1deg); }
html[data-ground="1"] .hero-card { border-color: #FEF1DF; box-shadow: 8px 8px 0 #88A31F; }
.hero-card .eyebrow { color: #4B5A0F; }
.hero-card .display { color: #56000E; font-size: var(--t5); max-width: 16ch; }
.hero-card .lead { max-width: 40ch; }
.hero-p2 { font-family: var(--font-hand); font-size: var(--t2); color: #56000E; transform: rotate(-2deg); display: inline-block; margin-bottom: 0; }
.hero .cta-row { margin-top: var(--sp3); }
@media (min-width: 1024px) {
  .hero { min-height: 720px; align-items: end; }
  .hero-art { position: absolute; inset: 0; height: auto; }
  .hero-wrap { margin-top: 0; padding-top: 360px; padding-bottom: var(--sp6); }
  .hero-card { max-width: 540px; padding: var(--sp5) var(--sp5) var(--sp4); }
  .hero-card .display { font-size: var(--t6); } }

/* ---------- Home 2: "A quick look at my work". Each tile cross-fades through its own pictures ---------- */
.quick .sec-head { margin-bottom: var(--sp4); }
.quick-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp4) var(--sp3); }
.qtile:last-child { grid-column: 1 / -1; }
.qtile:last-child .qstack { aspect-ratio: 16 / 9; }
@media (min-width: 1024px) { .quick-grid { grid-template-columns: repeat(5, 1fr); gap: var(--sp4); } .qtile:last-child { grid-column: auto; } .qtile:last-child .qstack { aspect-ratio: 4 / 5; } }
.qtile { transform: rotate(var(--r)); }
.qcard { display: block; text-decoration: none; color: #0A0024; background: #FFFFFF; padding: 8px 8px 12px; border: var(--edge); border-radius: 16px; box-shadow: var(--hard);
  transition: transform 320ms var(--spring), box-shadow 220ms ease; }
.qstack { display: block; position: relative; aspect-ratio: 4 / 5; overflow: hidden; border-radius: 10px; background: #FFFBF4; }
.qstack img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transform: scale(1.08); transition: opacity 900ms cubic-bezier(.45, 0, .2, 1), transform 2600ms cubic-bezier(.2, .6, .2, 1); }
.qstack picture { display: contents; }
.qstack img.q-on { opacity: 1; transform: scale(1); }
.qcat { display: inline-block; margin-top: var(--sp2); background: #F2C0AB; color: #0A0024; padding: 2px 12px; border-radius: 999px; border: var(--edge-sm); font: 600 var(--t0)/1.4 var(--font-display); }

/* ---------- Home 3: her fursona signing her name says the intro in a speech bubble ---------- */
.hello-grid { display: grid; gap: var(--sp4); align-items: center; }
@media (min-width: 1024px) { .hello-grid { grid-template-columns: 5fr 7fr; gap: var(--sp6); } }
.signer { margin: 0; justify-self: center; width: min(100%, 340px); }
.signer img { width: 100%; aspect-ratio: 1; object-fit: contain; filter: drop-shadow(var(--signer-shadow, 6px 6px 0 #F2C0AB)); }
.bubble { position: relative; background: #FFFFFF; border: var(--edge); border-radius: 36px; box-shadow: var(--hard); padding: var(--sp5) var(--sp4); }
.bubble::before { content: ''; position: absolute; width: 34px; height: 34px; background: #FFFFFF; border-left: var(--edge); border-bottom: var(--edge); left: 50%; top: -19px; transform: translateX(-50%) rotate(135deg); }
@media (min-width: 1024px) { .bubble { padding: var(--sp6) var(--sp6) var(--sp5); } .bubble::before { left: -19px; top: 96px; transform: rotate(45deg); } }
.crew { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp2) var(--sp3); margin: var(--sp3) 0 var(--sp4); }
.crew-t { margin: 0; font-family: var(--font-hand); font-size: var(--t2); color: #56000E; }
.crew-dots { list-style: none; margin: 0; padding: 0; display: flex; gap: var(--sp2); }
.crew-dots li { display: flex; flex-direction: column; align-items: center; gap: 2px; font: 600 16px/1.2 var(--font-display); }
.crew-dots img { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; border: 2px solid #F2C0AB; transition: transform 300ms var(--spring); }
.crew-dots li:hover img { transform: rotate(-12deg) scale(1.15); }

/* ---------- Home 4: R3-3's three columns, one image each, a clear button each ---------- */
.svc-cols { list-style: none; margin: var(--sp4) 0 0; padding: 0; display: grid; gap: var(--sp4); }
/* Builder port fix (steer note, Monday, October 12, 2026 at 8:33 PM EDT): 1fr let the unbreakable three-word headings
   push the row 156 px past the content width at 1440. Three equal columns from 1280, headings at the phone size so they fit. */
@media (min-width: 1280px) { .svc-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp5); } .svc-col .h3 { font-size: 22px; } }
.svc-col { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--sp2); padding: var(--sp4); background: #FFFBF4; border: var(--edge); border-radius: 32px; box-shadow: var(--hard);
  transition: transform 320ms var(--spring), box-shadow 220ms ease; }
.svc-col p { margin-left: auto; margin-right: auto; }
.svc-col .btn { margin-top: auto; }
.svc-art { display: block; width: 170px; height: 170px; border-radius: 50%; overflow: hidden; border: 4px solid #F2C0AB; background: #FFFFFF; transition: transform 400ms var(--spring); }
.svc-art img, .svc-art picture { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 0; aspect-ratio: auto; }
.svc-col .svc-from { margin: var(--sp1) 0 0; }
.svc-col:hover { transform: var(--card-hover); box-shadow: var(--lift); }
.svc-col:hover .svc-art { transform: rotate(-6deg) scale(1.06); }

/* ---------- Home 5: one row of kind words that slides sideways on its own ---------- */
.testimonials { overflow: hidden; }
.tst-vp { display: flex; width: 100%; overflow: hidden; padding: var(--sp3) 0 var(--sp6); }
.tst-track { list-style: none; margin: 0; padding: 0 0 0 var(--sp4); display: flex; gap: var(--sp5); flex: none; animation: tst-slide 46s linear infinite; }
.tst-track > li { flex: none; width: 320px; }
@media (min-width: 1024px) { .tst-track > li { width: 460px; } }
.tst-track .tst { height: 100%; }
.tst-vp:hover .tst-track, .tst-vp:focus-within .tst-track { animation-play-state: paused; }
@keyframes tst-slide { to { transform: translateX(-100%); } }

/* ---------- Home 7: ONE Instagram feed slot ---------- */
.ig { background: #FFFFFF; border: var(--edge); border-radius: 28px; box-shadow: var(--hard); padding: var(--sp4); }
.ig-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp3); margin-bottom: var(--sp4); }
.ig-ico { display: grid; place-items: center; width: 52px; height: 52px; border-radius: 16px; background: #F2C0AB; color: #56000E; }
.ig-ico svg { width: 28px; height: 28px; fill: currentColor; }
.ig-handle { margin: 0 auto 0 0; font-size: var(--t1); } .ig-handle strong { font-family: var(--font-display); color: #56000E; }
.ig-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
@media (min-width: 1024px) { .ig-grid { grid-template-columns: repeat(6, 1fr); gap: var(--sp2); } }
.ig-tile { display: block; aspect-ratio: 1; overflow: hidden; border-radius: 10px; transition: transform 300ms var(--spring); }
.ig-tile img { width: 100%; height: 100%; object-fit: cover; transition: transform 500ms ease; }
.ig-tile:hover, .ig-tile:focus-visible { transform: rotate(-3deg) scale(1.05); } .ig-tile:hover img { transform: scale(1.12); }
.ig-note { margin: var(--sp3) 0 0; }

/* ---------- Home 8: R3-3's island box ---------- */
.support { background: #FEF1DF; }
.island { background: #56000E; color: #FEF1DF; border-radius: 48px; padding: var(--sp6) var(--sp4); text-align: center; box-shadow: var(--island-shadow, 10px 10px 0 #88A31F); --focus: #FEF1DF; }
.island .eyebrow { color: #F2C0AB; } .island .h2 { color: #FEF1DF; } .island p { margin-left: auto; margin-right: auto; }
.island .cta-row { justify-content: center; }
.island .btn-primary { background: #F2C0AB; color: #56000E; border-color: #FEF1DF; box-shadow: 4px 4px 0 #FEF1DF; }
.island .btn-secondary { --btn2-bg: transparent; --btn2-fg: #FEF1DF; --btn2-line: #FEF1DF; box-shadow: 4px 4px 0 #F2C0AB; }

/* ---------- doodles inside some sections (her Assets 2), the same one file, a softer ink ---------- */
.doodled { position: relative; isolation: isolate; }
.doodled::before { content: ''; position: absolute; inset: 0; z-index: -1; background-color: #F2C0AB; -webkit-mask: url(doodles.png) 40px 20px / 480px repeat; mask: url(doodles.png) 40px 20px / 480px repeat; }

/* ---------- About: Resources moved out of the footer (Global 10) ---------- */
.res-list { list-style: none; margin: var(--sp4) 0 0; padding: 0; display: grid; gap: var(--sp3); }
@media (min-width: 1024px) { .res-list { grid-template-columns: repeat(3, 1fr); } }
.res-card { display: flex; justify-content: space-between; align-items: center; gap: var(--sp3); min-height: 72px; padding: var(--sp3) var(--sp4); background: #FFFFFF; color: #0A0024; text-decoration: none; border: var(--edge); border-radius: 22px; box-shadow: var(--hard-sm);
  font: 600 var(--t1)/1.25 var(--font-display); transition: transform 320ms var(--spring), box-shadow 220ms ease; }
.res-go { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: #88A31F; color: #0A0024; transition: transform 320ms var(--spring); }
.res-card:hover .res-go { transform: rotate(45deg) scale(1.15); }

/* ---------- Portfolio: mediums are the primary group, worlds are secondary (Portfolio 1) ---------- */
.tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp2); overflow: visible; padding: 0; margin: var(--sp4) 0 var(--sp3); }
@media (min-width: 768px) { .tabs { display: flex; flex-wrap: wrap; gap: var(--sp3); } }
.tab { display: inline-flex; align-items: center; gap: 10px; min-width: 0; min-height: 60px; padding: 8px 20px 8px 8px; border: var(--edge); border-radius: 999px; background: #FFFBF4; color: #0A0024;
  font: 700 var(--t1)/1.15 var(--font-display); box-shadow: var(--hard-sm); text-align: left; transition: transform 300ms var(--spring), box-shadow 200ms ease, background-color 160ms ease; }
.tab:last-child:nth-child(odd) { grid-column: 1 / -1; }
.tab-pic { flex: none; width: 44px; height: 44px; border-radius: 50%; overflow: hidden; background: #FFFFFF; transition: transform 360ms var(--spring); }
.tab-pic img { width: 100%; height: 100%; object-fit: cover; }
.tab[aria-selected="true"] { background: #56000E; color: #FEF1DF; border-color: #56000E; }
.tab:hover .tab-pic, .tab:focus-visible .tab-pic { transform: rotate(-14deg) scale(1.15); }
.chips { gap: 6px var(--sp2); }
.chips-label { font-weight: 600; font-size: 16px; }
.chip { min-height: 44px; padding: 6px 12px; font-size: 16px; font-weight: 600; border: 2px solid #56000E; background: transparent; color: #0A0024; transition: transform 260ms var(--spring), background-color 160ms ease; }
.chip:hover, .chip:focus-visible { background: #FEF1DF; transform: translateY(-2px) rotate(-2deg); }
.chip[aria-pressed="true"] { background: #F2C0AB; outline: 3px solid #56000E; outline-offset: 2px; }
.pf-head .chip { background: #FEF1DF; }

/* every piece is a button that opens the viewer */
.piece-frame { display: block; width: 100%; font: inherit; color: inherit; cursor: zoom-in; text-align: left; position: relative;
  transition: transform 320ms var(--spring), box-shadow 220ms ease; }
.piece-frame img { transition: transform 600ms cubic-bezier(.2, .6, .2, 1); }
.piece-frame:hover img, .piece-frame:focus-visible img { transform: scale(1.04); }
.cast-art { display: block; width: 100%; padding: 0; cursor: zoom-in; transition: transform 320ms var(--spring), box-shadow 220ms ease; }
/* Portfolio 6, her answer 3: a comic of several pages looks stacked: pages peek out behind the cover, and a badge counts them */
.comic .piece-frame { cursor: pointer; }
.stack { display: block; position: relative; isolation: isolate; margin: 4px 22px 22px 0; }
.stack::before, .stack::after { content: ''; position: absolute; inset: 0; z-index: -1; border: var(--edge); border-radius: var(--radius); box-shadow: var(--hard-sm); transition: transform 360ms var(--spring); }
.stack::before { background: #FEF1DF; transform: translate(12px, 10px) rotate(3.5deg); }
.stack::after { background: #F2C0AB; transform: translate(22px, 20px) rotate(7deg); z-index: -2; }
.stack:hover::before { transform: translate(20px, 4px) rotate(7deg); }
.stack:hover::after { transform: translate(36px, 8px) rotate(13deg); }
.pages-badge { position: absolute; z-index: 2; right: 12px; top: 12px; background: #56000E; color: #FEF1DF; font: 700 16px/1 var(--font-display); padding: 8px 12px; border-radius: 999px; border: 2px solid #FEF1DF; transform: rotate(4deg); }

/* load on scroll (Portfolio 4) and the centred "Like what you see?" (Portfolio 3) */
.pf-more { display: flex; flex-direction: column; align-items: center; gap: var(--sp2); margin: var(--sp3) 0 var(--sp5); }
.pf-sentinel { display: block; width: 100%; height: 1px; }
/* PORT FIX (Tuesday, October 20, 2026): with script, site.js places each portfolio piece once and never moves it, so
   cards no longer jump between columns when more load. Without script the CSS columns above stay. */
.pf-grid.pf-placed { columns: auto; position: relative; }
.pf-grid.pf-placed > .piece { position: absolute; margin-bottom: var(--sp5); }
.pf-end { font-family: var(--font-hand); font-size: var(--t2); color: #56000E; margin: 0; text-align: center; }
.like { text-align: center; max-width: 720px; margin: var(--sp5) auto 0; padding: var(--sp6) var(--sp4); background: #FEF1DF; border: var(--edge-dash); border-radius: 40px; }
.like-h { font: 700 var(--t5)/1.05 var(--font-display); color: #56000E; margin: 0 auto var(--sp2); max-width: none; }
@media (min-width: 1024px) { .like-h { font-size: var(--t7); } }
.like p { margin-left: auto; margin-right: auto; }
.like .cta-row { justify-content: center; }

/* ---------- the viewer (Portfolio 2) ---------- */
.viewer { width: 100vw; height: 100dvh; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: #56000E; color: #FEF1DF; overflow: hidden; --focus: #FEF1DF; }
.viewer::backdrop { background: #56000E; }
.viewer[open] { display: grid; grid-template-rows: auto 1fr auto; }
.vw-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp2) var(--sp4); padding: var(--sp2) var(--sp3); }
.vw-title { margin: 0; font: 700 var(--t1)/1.2 var(--font-display); flex: 1 1 200px; }
.vw-count { margin: 0; font-weight: 600; }
.vw-tools { display: flex; gap: var(--sp2); }
.vw-btn, .vw-step { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; border: 2px solid #FEF1DF; background: #FEF1DF; color: #56000E; font: 700 26px/1 var(--font-display); cursor: pointer;
  transition: transform 260ms var(--spring), background-color 160ms ease; }
.vw-btn:hover, .vw-step:hover, .vw-btn:focus-visible, .vw-step:focus-visible { background: #F2C0AB; transform: scale(1.12) rotate(-6deg); }
.vw-btn:active, .vw-step:active { transform: scale(.9); }
.vw-stage { position: relative; overflow: hidden; touch-action: none; cursor: grab; display: grid; place-items: center; }
.vw-stage.zoomed { cursor: move; }
.vw-img { max-width: calc(100vw - 32px); max-height: calc(100dvh - 160px); width: auto; height: auto; object-fit: contain; transform-origin: center; user-select: none; -webkit-user-drag: none; border-radius: 8px; background: #FFFFFF; }
.vw-step { position: absolute; top: 50%; width: 56px; height: 56px; font-size: 40px; margin-top: -28px; }
.vw-prev { left: var(--sp2); } .vw-next { right: var(--sp2); }
@media (min-width: 1024px) { .vw-prev { left: var(--sp4); } .vw-next { right: var(--sp4); } .vw-step { width: 64px; height: 64px; } }
.vw-hint { margin: 0 auto; padding: var(--sp2) var(--sp3) var(--sp3); font-size: 16px; text-align: center; }

/* ---------- the footer (Global 10): short, rectangular, grounded. The hands live in it (Global 3, 4) ---------- */
.site-footer { background: #56000E; color: #FEF1DF; padding: 0 0 var(--sp4); --focus: #FEF1DF; --link: #FEF1DF; }
.hands { padding: var(--sp5) 0 var(--sp3); background: transparent; --hands-fg: #FEF1DF; }
.hands ul { max-width: 640px; align-items: flex-end; padding: 0 calc(var(--gutter) + 26px); }
.hands { overflow-x: clip; }
.hand { color: #FEF1DF; transition: transform 300ms var(--spring); }
.hand:hover, .hand:focus-visible { transform: translateY(-5px); } .hand:active { transform: translateY(2px) scale(.96); }
/* Global 3: equal visual size. Measured on her art: the fist of a side hand is 162 x 253 of its 312 x 253 image, the fist
   of the top hand 208 x 216 of 208 x 356. Equal fist area puts the top hand at 0.64 of a side hand's width (92 and 58 px,
   140 and 90 px). Each side
   hand's palm sits at 74% (or 26%) of its image, so the image shifts by 24% of its width to centre the palm on its label. */
.hand-prev .hand-img img, .hand-next .hand-img img { width: 92px; }
.hand-top .hand-img img { width: 52px; }
.hands li { flex: none; } .hand-lbl { white-space: nowrap; }
@media (min-width: 1024px) { .hand-prev .hand-img img, .hand-next .hand-img img { width: 140px; } .hand-top .hand-img img { width: 80px; } }
.hand-prev .hand-img { transform: translateX(-24%); } .hand-next .hand-img { transform: translateX(24%); }
.hand-to { color: #FEF1DF; }
.foot-bar { display: grid; grid-template-columns: 72px 1fr; gap: var(--sp3) var(--sp4); align-items: center; padding-top: var(--sp4); padding-bottom: var(--sp3); border-top: 2px dashed #F2C0AB; }
@media (min-width: 1024px) { .foot-bar { grid-template-columns: auto 1fr auto; gap: var(--sp5); } }
@media (max-width: 1023px) { .foot-reach { grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; } .foot-logo { width: 72px; } .soc-icons { gap: 6px; } }
.foot-logo { display: inline-block; width: 88px; border-radius: 12px; transition: transform 360ms var(--spring); }
.foot-logo img { width: 100%; height: auto; }
.foot-logo:hover, .foot-logo:focus-visible { transform: rotate(-8deg) scale(1.08); }
.foot-words p { margin: 0 0 var(--sp1); }
.foot-reach { display: flex; flex-direction: column; gap: var(--sp2); align-items: flex-start; }
@media (min-width: 1024px) { .foot-reach { align-items: flex-end; } }
.mail { color: #FEF1DF; font-weight: 700; display: inline-block; padding: 10px 0; min-height: 44px; }
.soc { --soc-bg: #FEF1DF; --soc-fg: #56000E; --soc-line: #FEF1DF; transition: transform 300ms var(--spring), background-color 160ms ease; }
.soc:hover, .soc:focus-visible { transform: translateY(-5px) rotate(-12deg) scale(1.12); background: #F2C0AB; }
.soc:active { transform: scale(.88); }
.preview-note { font-size: 16px; margin-top: var(--sp2); padding-bottom: 0; max-width: none; }

/* ---------- the gecko page doll (Global 1): bare, fixed bottom right, alive ---------- */
.doll { position: fixed; right: 10px; bottom: 0; z-index: 45; width: 72px; height: 72px; padding: 0; border: 0; background: transparent; cursor: pointer; transform-origin: 50% 100%;
  transition: transform 420ms var(--spring); font-size: 16px; }
@media (min-width: 1024px) { .doll { right: 22px; width: 104px; height: 104px; } }
.doll img { width: 100%; height: 100%; object-fit: contain; object-position: 50% 100%; transform-origin: 50% 100%; }
@keyframes gecko-idle { 0%, 100% { transform: translateY(0) rotate(0); } 12% { transform: translateY(-3px) rotate(-3deg); } 24% { transform: translateY(0) rotate(0); }
  36% { transform: translateY(-3px) rotate(3deg); } 48% { transform: translateY(0) rotate(0); } 60% { transform: translateY(26%) rotate(0); } 66% { transform: translateY(26%) rotate(-4deg); }
  74% { transform: translateY(-6px) rotate(2deg) scale(1.04); } 82% { transform: translateY(0) rotate(0); } }
.doll-say { position: absolute; right: 70%; bottom: 82%; background: #FFFFFF; color: #56000E; border: 2px solid #56000E; border-radius: 16px 16px 4px 16px; padding: 4px 10px; font: 700 16px/1.2 var(--font-display);
  white-space: nowrap; opacity: 0; transform: scale(.6) translateY(6px); transform-origin: 100% 100%; transition: opacity 160ms ease, transform 300ms var(--spring); pointer-events: none; }
.doll:hover .doll-say, .doll:focus-visible .doll-say { opacity: 1; transform: none; }
.doll:hover img, .doll:focus-visible img { animation-play-state: paused; }
.doll:hover, .doll:focus-visible { transform: rotate(-8deg) scale(1.1); }
.doll:active { transform: scale(.9); }
.doll-zz { position: absolute; left: 0; top: 4px; font: 700 18px/1 var(--font-display); color: #56000E; background: #FFFFFF; border-radius: 999px; padding: 2px 8px; display: none; }
.doll-zz i { font-style: normal; font-size: 16px; }
html[data-motion="nap"] .doll img { animation: none; }
html[data-motion="nap"] .doll-zz { display: block; }

/* ---------- 404 (Global 12, her answer 5) ---------- */
.nf { min-height: 70vh; }
.nf-grid { display: grid; gap: var(--sp5); align-items: center; }
@media (min-width: 1024px) { .nf-grid { grid-template-columns: 6fr 6fr; gap: var(--sp7); } }
.nf-stage { display: flex; flex-direction: column; align-items: center; gap: var(--sp4); }
.ily { position: relative; width: min(100%, 420px); }
.nf { overflow-x: clip; }
.ily-img { width: 100%; height: auto; transform-origin: 50% 80%; }
/* Revision 6 (Task 5146, C2): no idle shake. ily-twitch is the same shake, retimed to play ONCE per miss (site.js adds
   .twitch to div.ily on a miss), 650 ms. */
@keyframes ily-twitch { 0%, 100% { transform: rotate(0); } 15% { transform: rotate(-4deg) translateY(-6px); } 40% { transform: rotate(3deg); } 65% { transform: rotate(-2deg) translateY(-3px); } 85% { transform: rotate(0); } }
/* Revision 2 (her words, Task 4617): no pink glow. Slow white sprinkles drift NEAR the pet (around its edges, never on
   the X): four-point sparkles, white with a thin wine line so they read on cream, each rising and fading on its own slow
   clock (7 to 11 s). The "!!" is a burnt-out S squiggle: a wine smoke curl with a puff, swaying gently. Both stop under
   Nap time and reduced motion. */
.ily-sprinkles { position: absolute; inset: -8% -6%; pointer-events: none; }
.ily-sprinkles i { position: absolute; width: var(--s, 18px); aspect-ratio: 1; background: none;
  opacity: 0; filter: drop-shadow(0 0 5px #FFFFFF) drop-shadow(0 0 2px #FFFFFF); animation: ily-sprinkle var(--d, 9s) ease-in-out var(--dl, 0s) infinite; }
.ily-sprinkles i::before { content: ''; position: absolute; inset: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5c.9 5.3 2.6 7.6 9.5 10.5-6.9 2.9-8.6 5.2-9.5 10.5-.9-5.3-2.6-7.6-9.5-10.5C9.4 9.1 11.1 6.8 12 1.5z' fill='%23FFFFFF' stroke='%2356000E' stroke-width='2.4' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
.ily-sprinkles i:nth-child(1) { left: 2%; top: 12%; --s: 30px; --d: 9s; }
.ily-sprinkles i:nth-child(2) { left: 18%; top: -4%; --s: 22px; --d: 11s; --dl: -3s; }
.ily-sprinkles i:nth-child(3) { left: 66%; top: 0%; --s: 34px; --d: 10s; --dl: -6s; }
.ily-sprinkles i:nth-child(4) { left: 90%; top: 26%; --s: 24px; --d: 8s; --dl: -2s; }
.ily-sprinkles i:nth-child(5) { left: 92%; top: 64%; --s: 30px; --d: 10.5s; --dl: -7s; }
.ily-sprinkles i:nth-child(6) { left: 0%; top: 56%; --s: 24px; --d: 9.5s; --dl: -4.5s; }
.ily-sprinkles i:nth-child(7) { left: 30%; top: 88%; --s: 20px; --d: 7.5s; --dl: -1s; }
@keyframes ily-sprinkle { 0% { opacity: 0; transform: translateY(14px) rotate(0) scale(.6); } 25% { opacity: 1; } 60% { opacity: .9; transform: translateY(-10px) rotate(40deg) scale(1); }
  100% { opacity: 0; transform: translateY(-30px) rotate(80deg) scale(.7); } }
.ily-fizzle { position: absolute; right: 2%; top: -18%; width: clamp(56px, 17%, 84px); height: auto; overflow: visible; transform-origin: 70% 95%; animation: ily-fizzle 3.6s ease-in-out infinite; pointer-events: none; }
.ily-fizzle .fz-spark { fill: none; stroke: #56000E; stroke-width: 4; stroke-linecap: round; }
.ily-fizzle .fz-s { fill: none; stroke: #56000E; stroke-width: 7; stroke-linecap: round; stroke-linejoin: round; }
.ily-fizzle .fz-puff { fill: #FFFFFF; stroke: #56000E; stroke-width: 3; stroke-linejoin: round; }
@keyframes ily-fizzle { 0%, 100% { transform: rotate(-4deg); } 50% { transform: rotate(6deg) translateY(-3px); } }
.ily-shock { position: absolute; inset: -6% -4%; pointer-events: none; }
.ily-shock i { position: absolute; width: 6px; height: 34px; border-radius: 3px; background: #56000E; transform-origin: 50% 160%; animation: ily-shock 1s ease-in-out infinite; }
.ily-shock i:nth-child(1) { left: 6%; top: 18%; transform: rotate(-50deg); } .ily-shock i:nth-child(2) { left: 18%; top: 2%; transform: rotate(-25deg); animation-delay: .1s; }
.ily-shock i:nth-child(3) { left: 44%; top: -6%; transform: rotate(0deg); animation-delay: .2s; } .ily-shock i:nth-child(4) { left: 92%; top: 30%; transform: rotate(55deg); animation-delay: .15s; }
.ily-shock i:nth-child(5) { left: 4%; top: 60%; transform: rotate(-80deg); animation-delay: .25s; } .ily-shock i:nth-child(6) { left: 90%; top: 66%; transform: rotate(80deg); animation-delay: .05s; }
@keyframes ily-shock { 50% { opacity: .2; } }
.ily.awake .ily-img { animation: ily-wake 900ms var(--spring) 1; }
@keyframes ily-wake { 30% { transform: translateY(-40px) rotate(-180deg); } 100% { transform: rotate(-360deg); } }
.ily.woke .ily-shock, .ily.woke .ily-fizzle { display: none; }
.nf-code { font: 700 clamp(72px, 18vw, 150px)/0.9 var(--font-display); color: #88A31F; -webkit-text-stroke: 3px #56000E; margin: 0 0 var(--sp2); letter-spacing: -0.02em; }
.nf-text .display { color: #56000E; font-size: var(--t4); }
@media (min-width: 1024px) { .nf-text .display { font-size: var(--t5); } }
.nf-prize { margin-top: var(--sp5); padding: var(--sp4); background: #FFFFFF; border: var(--edge-dash); border-radius: 28px; animation: prize-pop 600ms var(--spring) 1; }
@keyframes prize-pop { from { transform: scale(.6) rotate(-6deg); opacity: 0; } }
.nf-prize-h { font: 700 var(--t2)/1.2 var(--font-display); color: #56000E; }
.nf-secret { aspect-ratio: 4 / 3; display: grid; place-items: center; text-align: center; padding: var(--sp4); background: #FEF1DF; border-radius: 16px; color: #0A0024; }
.confetti { position: fixed; z-index: 60; pointer-events: none; font-size: 26px; animation: confetti 1600ms cubic-bezier(.2, .6, .3, 1) forwards; }
@keyframes confetti { from { transform: translate(0, 0) rotate(0); opacity: 1; } to { transform: translate(var(--dx), var(--dy)) rotate(var(--rot)); opacity: 0; } }

/* =====================================================================================================================
   HOVER AND PRESS, EVERYWHERE (her answer 1). Hover and keyboard focus share one look; a press squashes.
   ===================================================================================================================== */
.btn { transition: transform 300ms var(--spring), box-shadow 220ms ease, background-color 160ms ease; box-shadow: var(--hard-sm); }
.btn:hover, .btn:focus-visible { transform: var(--hover-move); box-shadow: var(--lift); }
.btn:active { transform: var(--press-move); box-shadow: var(--press); transition-duration: 80ms; }
.island .btn:hover, .island .btn:focus-visible { box-shadow: 7px 7px 0 #88A31F; }
.world-card, .qcard, .res-card, .tier, .pet-card, .support-card { transition: transform 320ms var(--spring), box-shadow 220ms ease; }
.world-card:hover, .world-card:focus-visible, .qcard:hover, .qcard:focus-visible, .res-card:hover, .res-card:focus-visible, .piece-frame:hover, .piece-frame:focus-visible, .cast-art:hover, .cast-art:focus-visible, .tab:hover, .tab:focus-visible {
  transform: var(--card-hover); box-shadow: var(--lift); }
.world-card:active, .qcard:active, .res-card:active, .piece-frame:active, .cast-art:active, .tab:active, .svc-col:active { transform: var(--card-press); box-shadow: var(--press); transition-duration: 80ms; }
.world-art img, .qstack, .cast-art img { transition: transform 600ms cubic-bezier(.2, .6, .2, 1); }
.world-card:hover .world-art img, .world-card:focus-visible .world-art img { transform: scale(1.07) rotate(-1deg); }
.more { transition: transform 260ms var(--spring); }
.more:hover, .more:focus-visible { transform: translateX(6px) rotate(-2deg); }
.svc-jump a, .world-nav a { transition: transform 260ms var(--spring); }
.svc-jump a:hover, .svc-jump a:focus-visible { transform: translateY(-3px) rotate(-2deg); }
.modal-close { transition: transform 260ms var(--spring); } .modal-close:hover, .modal-close:focus-visible { transform: rotate(-4deg) scale(1.06); }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; }
.band-matcha { --focus: #0A0024; }

/* =====================================================================================================================
   MOTION. Nap time (data-motion="nap") stops every block that moves on its own; prefers-reduced-motion starts the site
   napping and also drops the big hover movement. Hover colour and shadow changes stay.
   ===================================================================================================================== */
html[data-motion="nap"] .tst-track, html[data-motion="nap"] .ily-img, html[data-motion="nap"] .ily-sprinkles i, html[data-motion="nap"] .ily-fizzle,
html[data-motion="nap"] .ily-shock i { animation-play-state: paused; }
/* Nap time freezes the sprinkles where they are; a sprinkle frozen at opacity 0 shows as a still sparkle, never vanishes. */
html[data-motion="nap"] .ily-sprinkles i { animation: none; opacity: .9; }
html[data-motion="nap"] .qstack img { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .ily-sprinkles i, .ily-fizzle { animation: none !important; } .ily-sprinkles i { opacity: .9; }
  .btn:hover, .btn:focus-visible, .btn:active, .world-card:hover, .qcard:hover, .res-card:hover, .piece-frame:hover, .cast-art:hover, .tab:hover, .svc-col:hover, .nav-a:hover, .nav-a:focus-visible,
  .soc:hover, .hand:hover, .doll:hover, .nav-a:hover .np, .more:hover { transform: none !important; } }

/* =====================================================================================================================
   REVISION (Step 4591.rev.1, Task 4591): Destiny's round 4 answers
   ===================================================================================================================== */
/* Testimonials on a phone: the initials sit above the quote, so the words get the card's full width (beside the
   initials the column was too narrow and the text ran past the card). */
@media (max-width: 767px) { .tst { grid-template-columns: 1fr; padding: var(--sp4); } .tst blockquote, .tst figcaption { grid-column: 1; } }

/* Every line holds two words (Task 4591): a three-word heading never wraps (glue), so on a phone the long ones get a
   size that fits the column, and a four-tier list runs two across on a desktop so each tier's words have room. */
@media (max-width: 559px) { .svc-block .h2, .svc-col .h3 { font-size: 22px; } }
/* Revision 4: the four-tier rule moved to the REVISION 4 section (two across from 768 px, three from 1024 px). */

/* Hands (her words): Back to top a little smaller (58 to 52 px on a phone, 90 to 80 px from 1024 px, set above), and its
   label on the same baseline as Previous and Next. The page name under Previous and Next ("Home") hangs below its
   label out of flow, so all three labels are one line and the row's flex-end puts their baselines level. */
.hand-lbl { position: relative; }
.hand-to { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); white-space: nowrap; }
.hands ul { padding-bottom: 1.5em; }

/* Home, "Hi, I'm Destiny!" (her words): the name-sign fursona larger, in a circle, tucked a little behind the bubble. */
.hello-grid { gap: 0; }
.signer { position: relative; z-index: 0; width: min(86%, 360px); margin-bottom: -44px; }
.signer-ring { display: block; aspect-ratio: 1; border-radius: 50%; overflow: hidden; background: #F2C0AB; border: var(--edge); box-shadow: var(--hard); }
.signer-ring picture { display: block; width: 100%; height: 100%; }
.signer .signer-img { width: 100%; height: 100%; aspect-ratio: 1; object-fit: cover; filter: none; }
.hello .bubble { z-index: 1; }
@media (min-width: 1024px) { .hello-grid { grid-template-columns: 6fr 7fr; } .signer { width: min(100%, 480px); justify-self: end; margin: 0 -64px 0 0; } }

/* About, first section (her words): a real-life photo above the collage video, behind it. Revision 2: her photo, cropped
   4:5 with her face high; the video overlaps less than the stand-in did (16% of the column, not 34%), so her face down
   to the chin stays clear of it. */
.about-media { position: relative; }
.about-photo { position: relative; z-index: 0; width: 58%; aspect-ratio: 4 / 5; margin: 0 0 -16% 6%; display: grid; justify-items: center; align-content: start; gap: var(--sp1); padding-top: var(--sp4) !important;
  background: #FFFBF4; border: var(--edge-dash); border-radius: var(--radius); box-shadow: var(--hard-sm); padding: var(--sp3); text-align: center; }
.about-photo { padding: 0 !important; border: var(--edge); overflow: hidden; background: #FEF1DF; }
.about-photo picture, .about-photo img { display: block; width: 100%; height: 100%; }
.about-photo img { object-fit: cover; object-position: 50% 30%; }
.about-media .intro-vid { position: relative; z-index: 1; margin: 0; }

/* About, FAQ: a stand-in block; each question opens on its own (details and summary, keyboard native). */
.faq-list { display: grid; gap: var(--sp3); max-width: 860px; margin-top: var(--sp4); }
.faq-item { background: #FFFFFF; border: var(--edge); border-radius: var(--radius); box-shadow: var(--hard-sm); }
.faq-item summary { display: flex; align-items: center; justify-content: space-between; gap: var(--sp3); min-height: 56px; padding: var(--sp2) var(--sp4); cursor: pointer; list-style: none;
  font: 700 var(--t1)/1.3 var(--font-display); color: #56000E; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: '+'; flex: none; font-size: 28px; line-height: 1; transition: transform 260ms var(--spring); }
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p { margin: 0; padding: 0 var(--sp4) var(--sp4); }

/* Hire Me (her words): her own tier pictures have no outline, which looked odd around transparent art. */
.tier-ex.tier-own img { border: 0; background: transparent; }

/* Hire Me, "How big is my project?" (her words): closed on load, one button opens it. Each role is a box with a bold
   coloured title, in columns (the description sits under its title, so a role reads as one thing). */
.guide-toggle { margin-top: var(--sp2); }
.guide-ico { display: inline-block; width: 12px; height: 12px; border-right: 3px solid currentColor; border-bottom: 3px solid currentColor; transform: rotate(45deg) translate(-2px, -2px); margin-right: var(--sp2); transition: transform 260ms var(--spring); }
.guide-toggle[aria-expanded="true"] .guide-ico { transform: rotate(-135deg) translate(-2px, -2px); }
.guide-body { margin-top: var(--sp5); }
.role-boxes { list-style: none; margin: var(--sp3) 0 var(--sp5); padding: 0; display: grid; gap: var(--sp3); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.role-box { background: #FFFFFF; border: var(--edge); border-radius: var(--radius); box-shadow: var(--hard-sm); padding: var(--sp3) var(--sp3) var(--sp4); margin: 0; }
.role-box p { margin: var(--sp2) 0 0; }
.role-t { display: inline-block; margin: 0; padding: 4px 14px; border-radius: 12px; font: 700 var(--t1)/1.25 var(--font-display); background: #56000E; color: #FEF1DF; }
.role-box:nth-child(even) .role-t { background: #88A31F; color: #0A0024; }
.tick-box { background: #FFFFFF; border: var(--edge); border-radius: var(--radius); box-shadow: var(--hard-sm); padding: var(--sp4); }
.ticks { list-style: none; margin: var(--sp3) 0 0; padding: 0; display: grid; gap: var(--sp2); }
.tick { display: flex; align-items: flex-start; gap: var(--sp2); min-height: 44px; cursor: pointer; }
.tick input { flex: none; width: 26px; height: 26px; margin: 0; accent-color: #56000E; cursor: pointer; }
.tick input:checked + span { text-decoration: line-through; text-decoration-color: #88A31F; text-decoration-thickness: 3px; }
.tick-note { margin-top: var(--sp3); }

/* ---------- LINKS (Task 4591): her link hub. Revision 2 (Task 4617): ONE layout, her mix, on a patterned red ---------- */
/* Patterned, not solid (her words): her doodle marks (the site background's one tile, assets/doodles.png) in Matcha on the
   wine, exactly as the site ground. Every label sits on its own card, never on the pattern, so its contrast is unchanged. */
.lk-page { position: relative; isolation: isolate; background: #56000E; padding: var(--sp6) 0 var(--sp7); border-block: var(--edge); }
.lk-wrap { max-width: 720px; }
.lk-card { background: #FFFBF4; border: 3px solid #56000E; border-radius: 36px; box-shadow: 10px 10px 0 #88A31F; padding: var(--sp5) var(--sp4) var(--sp5); }
@media (min-width: 768px) { .lk-card { padding: var(--sp6); } }
.lk-head { display: flex; align-items: center; gap: var(--sp3); }
@media (max-width: 559px) { .lk-head { flex-direction: column; text-align: center; } .lk-name { font-size: var(--t2); } .lk-icons { justify-content: center; } }

.lk-name { margin: 0; font: 700 var(--t3)/1.15 var(--font-display); color: #56000E; }
.lk-bio { margin: var(--sp1) 0 0; }
.lk-icons { list-style: none; margin: var(--sp4) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp2); }
.lk.lk-icon { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; background: #56000E; color: #FEF1DF; transition: transform 300ms var(--spring); }
.lk-icon svg { width: 22px; height: 22px; fill: currentColor; }
.lk-icon:hover, .lk-icon:focus-visible { transform: translateY(-4px) rotate(-10deg) scale(1.08); background: #3F000A; }
.lk-g { margin: var(--sp5) 0 var(--sp2); font: 700 var(--t0)/1.2 var(--font-display); color: #56000E; text-transform: uppercase; letter-spacing: .06em; }
.lk-list { list-style: none; margin: var(--sp4) 0 0; padding: 0; }
.lk-g + .lk-list { margin-top: 0; }
.lk { display: flex; align-items: center; gap: var(--sp3); text-decoration: none; color: #0A0024; font: 600 var(--t1)/1.25 var(--font-display);
  background: #FFFFFF; border: var(--edge); box-shadow: var(--hard-sm); transition: transform 260ms var(--spring), box-shadow 200ms ease; }
.lk:hover, .lk:focus-visible { transform: var(--hover-move); box-shadow: var(--lift); }
.lk:active { transform: var(--press-move); box-shadow: var(--press); }
.lk-t { flex: 1; min-width: 0; }
.lk-go { flex: none; font-size: 24px; color: #56000E; }
.lk-pic { flex: none; display: block; overflow: hidden; border-radius: 14px; border: var(--edge-sm); background: #FEF1DF; }
.lk-pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.lk-pic-kofi { display: grid; place-items: center; background: #56000E; color: #FEF1DF; }
.lk-pic-kofi svg { width: 55%; height: 55%; fill: currentColor; }
.lk-pin { background: #88A31F; }
.lk-kofi { background: #F2C0AB; }
.lk-note { margin: var(--sp5) 0 0; }

/* The lists: layout 3's compact pills, every link on about one screen, 48 px targets. */
.lk-list { display: flex; flex-wrap: wrap; gap: var(--sp2); }
.lk-list .lk { max-width: 100%; min-height: 48px; padding: 8px 18px; border-radius: 999px; font-size: var(--t0); gap: var(--sp2); }
.lk-list .lk-go { display: none; }
.lk-list .lk-t { flex: 0 1 auto; min-width: 0; }
.lk-g { margin-top: var(--sp4); }
/* The pinned entries with a picture ("Adopt a Gek today!", "Download the Secret ASL font"): layout 2's green picture
   boxes, two across, picture first. */
.lk-list.lk-pins { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp3); }
.lk-pins .lk.has-pic { flex-direction: column; justify-content: center; text-align: center; height: 100%; padding: var(--sp2) var(--sp2) var(--sp3); border-radius: 20px; font-size: var(--t0); }
.lk-pins .lk.has-pic .lk-pic { width: 100%; aspect-ratio: 1; height: auto; }
.lk-pins .lk.has-pic .lk-t { flex: none; }
/* The Ko-fi entry: layout 1's big pink button, full width under the two boxes, its Ko-fi tile and arrow kept. */
.lk-pins li:has(> .lk-kofi) { grid-column: 1 / -1; }
.lk-pins .lk.lk-kofi { min-height: 88px; padding: 10px 20px 10px 10px; border-radius: 24px; font-size: var(--t2); gap: var(--sp3); }
.lk-pins .lk.lk-kofi .lk-pic { width: 68px; height: 68px; }
.lk-pins .lk.lk-kofi .lk-t { flex: 1; }
.lk-pins .lk.lk-kofi .lk-go { display: block; }
@media (max-width: 559px) { .lk-pins .lk.lk-kofi { font-size: var(--t1); } }

/* Her menu picture buttons (steer note, October 12, 2026): her GIF art, whole and unmasked, beside each word. Rest by
   default, hover art on hover or keyboard focus, click art while pressed. No circle, no crop, no extra motion. */
.np.np-btn { width: auto; height: 40px; border-radius: 0; overflow: visible; background: none; box-shadow: none; display: flex; align-items: center; }
.np-btn picture, .np-btn img { display: block; height: 40px; width: auto; }
.np-btn .h-hover, .np-btn .h-press { display: none; }
.nav-a:hover .np-btn .h-rest, .nav-a:focus-visible .np-btn .h-rest { display: none; }
.nav-a:hover .np-btn .h-hover, .nav-a:focus-visible .np-btn .h-hover { display: block; }
.nav-a:active .np-btn .h-rest, .nav-a:active .np-btn .h-hover { display: none; }
.nav-a:active .np-btn .h-press { display: block; }
.nav-a:hover .np.np-btn, .nav-a:focus-visible .np.np-btn, .nav-a:active .np.np-btn { transform: none; box-shadow: none; filter: none; }
/* Revision 2: hover and click art are Matcha now, and the current page's pill is Matcha, so on the current item the
   Wine rest art stays in every state (Matcha on Matcha would vanish). */
.nav-a[aria-current="page"] .np-btn .h-rest { display: block !important; }
.nav-a[aria-current="page"] .np-btn .h-hover, .nav-a[aria-current="page"] .np-btn .h-press { display: none !important; }
.np-logo img { height: 34px; }
.nav-a:hover .np-logo img, .nav-a:focus-visible .np-logo img { transform: rotate(-12deg) scale(1.12); transition: transform 300ms var(--spring); }
@media (min-width: 1024px) and (max-width: 1279px) { .np.np-btn, .np-btn picture, .np-btn img { height: 32px; } .np-logo img { height: 28px; } }

/* Case Studies (steer note, October 12, 2026): a placeholder page, five studies, the need, the process, the result. */
.cs-head { background: #F2C0AB; border-bottom: var(--edge); }
.cs-list { background: #FEF1DF; }
.cs-items { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp6); }
.cs-item { display: grid; gap: var(--sp4); align-items: start; background: #FFFFFF; border: var(--edge); border-radius: var(--radius); box-shadow: var(--hard); padding: var(--sp4); }
@media (min-width: 1024px) { .cs-item { grid-template-columns: 5fr 7fr; gap: var(--sp5); padding: var(--sp5); } .cs-item:nth-child(even) .cs-art { order: 2; } }
.cs-art { position: relative; border-radius: 14px; overflow: hidden; border: var(--edge-sm); background: #FFFBF4; }
.cs-art img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; opacity: .35; }
.cs-art-ph { position: absolute; inset: 0; display: grid; place-items: center; padding: var(--sp3); text-align: center; font-weight: 600; }
.cs-text .h2 { margin-top: 0; margin-bottom: 0; }
.cs-sub { margin: var(--sp1) 0 0; font: 600 var(--t1)/1.3 var(--font-display); color: #0A0024; }
.cs-steps { margin: var(--sp3) 0 var(--sp4); display: grid; gap: var(--sp2); }
.cs-steps dt { font: 700 var(--t1)/1.25 var(--font-display); color: #56000E; }
.cs-steps dd { margin: 2px 0 0; }
.cs-more { margin: var(--sp5) 0 0; text-align: center; font-family: var(--font-hand); font-size: var(--t2); color: #56000E; }

/* Revision 2 (Task 4617): her two optional art pieces, About only. The matcha float leans on the "When I'm not drawing"
   picture (she sips matcha); the sketchbook opens the closing section. Both whole, transparent, never cropped. */
.off-art { position: relative; }
.off-matcha { position: absolute; left: -2%; bottom: -10%; width: clamp(96px, 26%, 150px); transform: rotate(-8deg); pointer-events: none; }
.off-matcha img, .close-art img { display: block; width: 100%; height: auto; border: 0; box-shadow: none; border-radius: 0; transform: none; }
.off-art > picture.off-matcha img { filter: drop-shadow(4px 4px 0 rgba(86, 0, 14, .25)); }
.close-art { display: block; width: min(100%, 520px); margin: 0 0 var(--sp4); }
@media (min-width: 1024px) { .closing .wrap { display: grid; grid-template-columns: 7fr 5fr; column-gap: var(--sp6); align-items: center; }
  .closing .wrap > :not(.close-art) { grid-column: 1; } .close-art { grid-column: 2; grid-row: 1 / span 3; margin: 0; width: 100%; } }

/* =====================================================================================================================
   REVISION 3 (Step 4701.rev.1, Task 4701): Destiny's review of revision 2, Tuesday, October 13, 2026
   ===================================================================================================================== */
/* Part A, nav item 2: the "Hire Me" button's hard shadow is Matcha, not Wine (rest, hover lift and press). */
.btn-hire { box-shadow: 3px 3px 0 #88A31F; }
.btn-hire:hover, .btn-hire:focus-visible { box-shadow: 7px 7px 0 #88A31F; }
.btn-hire:active { box-shadow: 1px 1px 0 #88A31F; }
/* Part A, nav item 3: Nap time shows its state with a symbol after the words. Two bars (pause) while things move; a
   triangle (play) once napping. Drawn in CSS, Wine, 14 x 16 px, so it reads at 1x and sits on the text's centre line. */
.nap-sym { flex: none; display: inline-block; width: 12px; height: 14px; border-left: 4px solid #56000E; border-right: 4px solid #56000E; margin-left: 2px; }
html[data-motion="nap"] .nap-sym { width: 0; height: 0; border-right: 0; border-left: 13px solid #56000E; border-top: 8px solid transparent; border-bottom: 8px solid transparent; }
@media (max-width: 559px) { .nap-hdr .nap-sym { margin-left: 0; } }
@media (min-width: 1024px) and (max-width: 1279px) { .nap-hdr .nap-sym { margin-left: 0; } }
/* Part A, nav item 4: Home's icon swaps to its Matcha twin on hover, focus and press through the same .h-rest, .h-hover and
   .h-press rules as the GIF pictures (build.mjs navPic); nothing else is needed here. */

/* Green and pink buttons (revision 3, global rule): a Matcha or Peach fill with Midnight ink labels, measured in
   contrast.mjs (ink on matcha 7.04:1, ink on peach 12.43:1), and the Wine line every button carries. */
.btn-green { background: #88A31F; color: #0A0024; border-color: #56000E; }
.btn-green:hover, .btn-green:focus-visible { background: #88A31F; color: #0A0024; }
.btn-pink { background: #F2C0AB; color: #0A0024; border-color: #56000E; }
.btn-pink:hover, .btn-pink:focus-visible { background: #F2C0AB; color: #0A0024; }
.island .btn-green { border-color: #FEF1DF; box-shadow: 4px 4px 0 #F2C0AB; }
.btn-green .ph, .btn-pink .ph { --ph: #0A0024; }

/* Part B, Home items 1 and 5: a section's own pause, in the About video's style (symbol plus words). The symbol is the
   video toggle's: a triangle while paused (Play ...), two bars while moving (Pause ...). */
.sec-toggle { min-height: 44px; padding: 8px 18px; box-shadow: var(--hard-xs); }
.sec-toggle .vid-ico { margin-right: 0; }
.sec-toggle.playing .vid-ico { width: 14px; height: 16px; border: 0; border-left: 5px solid currentColor; border-right: 5px solid currentColor; }
.sec-toggle[aria-disabled="true"] { cursor: not-allowed; }
.testimonials[data-paused="true"] .tst-track, .quick[data-paused="true"] .qstack img { animation-play-state: paused; transition: none; }

/* Part B, Home item 2: "My crew:" sits on the pet names' baseline. The names are the last line of each column, so the
   row aligns everything by its LAST baseline. */
.crew { align-items: last baseline; }
.crew-dots { align-items: last baseline; }

/* Part B, Home item 3: the three service cards. Equal columns (minmax(0, 1fr), so a long word cannot widen one), a
   title that may break once between its two held parts, and the whole card is one link: the visible button's ::after
   covers the card, so there is one tab stop per card, and the focus ring is drawn on the card. */
@media (min-width: 1024px) { .svc-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp4); } }
.svc-col { position: relative; min-width: 0; cursor: pointer; }
.svc-col .svc-name { max-width: 100%; overflow-wrap: normal; font-size: clamp(22px, 2.1vw + 8px, var(--t3)); }
@media (max-width: 559px) { .svc-col .svc-name { font-size: 22px; } }
.svc-n { display: inline-block; white-space: nowrap; }
.svc-go::after { content: ''; position: absolute; inset: 0; border-radius: 32px; }
.svc-col .btn { max-width: 100%; white-space: normal; text-align: center; }
.svc-go:focus-visible { outline: none; }
.svc-col:focus-within { outline: 3px solid var(--focus); outline-offset: 4px; }
.svc-col:has(.svc-go:focus-visible) { transform: var(--card-hover); box-shadow: var(--lift); }
/* The button never moves on its own inside a card (Eric, Tuesday, October 20, 2026: the button flickered while the mouse
   was on the card text). A transform on .svc-go makes it the containing block of its own ::after, so the cover shrank
   to the button, the pointer left the link, the hover ended and the cover grew back, over and over. The CARD lifts
   instead (.svc-col:hover above), and the button only takes the lifted shadow. test/r4-hover-browser.test.mjs. */
.svc-col .svc-go:hover, .svc-col .svc-go:focus-visible, .svc-col .svc-go:active { transform: none; }
.svc-col:hover .svc-go, .svc-col:has(.svc-go:focus-visible) .svc-go { box-shadow: var(--lift); }

/* Part B, Home item 4: the testimonial strip, driven by site.js. Drag with a mouse, swipe on touch, or step with the
   < and > buttons at its sides. The CSS slide stays for a page without JavaScript. */
.tst-vp { position: relative; touch-action: pan-y; cursor: grab; user-select: none; -webkit-user-select: none; }
.tst-vp.dragging { cursor: grabbing; }
.tst-rail { display: flex; flex: none; will-change: transform; }
.tst-rail.js .tst-track { animation: none; }
.tst-vp a, .tst-vp img { -webkit-user-drag: none; }
.tst-arrow { position: absolute; z-index: 3; top: 50%; margin-top: -26px; display: grid; place-items: center; width: 52px; height: 52px; border-radius: 50%;
  border: var(--edge); background: #FFFBF4; color: #56000E; box-shadow: var(--hard-xs); cursor: pointer; transition: transform 260ms var(--spring); }
.tst-prev { left: var(--sp2); } .tst-next { right: var(--sp2); }
@media (min-width: 1024px) { .tst-prev { left: var(--sp4); } .tst-next { right: var(--sp4); } }
.tst-arrow:hover, .tst-arrow:focus-visible { transform: scale(1.1) rotate(-6deg); background: #F2C0AB; }
.tst-arrow:active { transform: scale(.92); }
.glyph { display: block; width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round; }
.tst figcaption { align-items: center; text-align: center; }
.tst { grid-template-rows: auto 1fr; }
.tst-cs { align-self: center; margin-top: var(--sp3); min-height: 44px; padding: 8px 18px; }
@media (min-width: 768px) { .tst figcaption { grid-column: 1 / -1; } }
/* On a phone the label and the four pets share one line: smaller photos and gaps, and the label one step smaller. The
   row is one line from 360 px up; at 320 and 340 px the label wraps above the pets (no room for both, measured). */
@media (max-width: 559px) { .crew { gap: var(--sp1) var(--sp2); flex-wrap: wrap; } .crew-t { font-size: 20px; } .crew-dots { gap: 6px; } .crew-dots img { width: 40px; height: 40px; } }
/* The footer's words and links may shrink with the column (at 320 px they ran 6 px past the screen in revision 2). */
.foot-words, .foot-reach { min-width: 0; } .mail { overflow-wrap: anywhere; }
/* At 320 px the screen-reader words inside the last hand's label sat at its end, 5 px past the screen, and widened the
   page. Pinned to the label's start, they take no room. */
.hand-lbl .sr { left: 0; top: 0; }

/* Every page from 320 px (revision 3; Step 4701.rev.2 checks seven widths from 320 to 1440). Revision 2 was only
   rendered at 390 and 1440, and at 320 a two-word glued chunk ("Destiny (Sakeozo)") or a grid item's minimum width ran
   past the screen on About, Hire Me, Links and Case Studies. Grid and flex items may shrink, and the biggest type
   steps down below 390 px. Nothing here changes a layout at 390 px or wider. */
.about-grid > *, .tier-list > li, .cs-items > li, .lk-head > div, .tl-beat > * { min-width: 0; }
/* Revision 4 (Decision recY3cDI1ibE1YFgd item 2): this one-column rule had no media query, so it beat base.css's
   columns at every width and Service 1's tiers stacked at 1440 px. It is for the narrow band it was written for. */
@media (max-width: 767px) { .tier-list, .cs-items { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 379px) {
  .display { font-size: 32px; } .h2 { font-size: 28px; } .h3 { font-size: 22px; } .lead { font-size: 19px; }
  .lk-name { font-size: 22px; } .lk-card { padding-left: var(--sp3); padding-right: var(--sp3); }
  .cs-item, .tier { padding-left: var(--sp3); padding-right: var(--sp3); }
  .foot-words { grid-column: 1 / -1; } .tier-name { font-size: 20px; } .tabs { grid-template-columns: minmax(0, 1fr); }
  .hands ul { padding: 0 calc(var(--gutter) + 14px); gap: var(--sp2); } .hand-lbl { font-size: 16px; } .hand-prev .hand-img img, .hand-next .hand-img img { width: 76px; } .hand-top .hand-img img { width: 46px; } }
@media (min-width: 360px) and (max-width: 389px) { .display { font-size: 38px; } }
/* The strip fades out under the < and > buttons (a mask, so the doodled ground shows through), so a button never sits
   on a quote's words. */
.tst-mask { flex: 1; min-width: 0; overflow: hidden; padding: var(--sp3) 0 var(--sp6); margin: calc(-1 * var(--sp3)) 0 calc(-1 * var(--sp6));
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 88px, #000 calc(100% - 88px), transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 88px, #000 calc(100% - 88px), transparent 100%); }
@media (min-width: 1024px) { .tst-mask { -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 120px, #000 calc(100% - 120px), transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 120px, #000 calc(100% - 120px), transparent 100%); } }
/* On a phone a card is nearly the screen's width, so a side button would sit on its words: below 768 px the < and >
   buttons sit under the strip, either side of its centre, and the strip does not fade. */
@media (max-width: 767px) { .tst-vp { padding-bottom: 84px; } .tst-mask { -webkit-mask-image: none; mask-image: none; }
  .tst-arrow { top: auto; bottom: 16px; margin-top: 0; } .tst-prev { left: calc(50% - 64px); } .tst-next { right: calc(50% - 64px); } }

/* Part C, Portfolio item 1: the selected medium is Matcha with Midnight words (not Wine), and a selected world tag has a
   bold Matcha outer edge (5 px) outside its Wine line, closed by a 2 px Wine line so the edge reads at 3:1 on peach and cream (Matcha on peach alone is 1.77:1), not the thin Wine double ring. The worlds page has no filters, so
   nothing changes there. */
.tab[aria-selected="true"] { background: #88A31F; color: #0A0024; border-color: #56000E; }
.chip[aria-pressed="true"] { background: #F2C0AB; outline: 0; border-color: #56000E; box-shadow: 0 0 0 5px #88A31F, 0 0 0 7px #56000E; font-weight: 700; }
.chip[aria-pressed="true"]:focus-visible { outline: 3px solid var(--focus); outline-offset: 8px; }

/* Part C, items 3 and 4: the viewer's controls carry SVG glyphs, centred on the circle by construction. */
.vw-btn .glyph { width: 24px; height: 24px; stroke-width: 3; }
.vw-step .glyph { width: 30px; height: 30px; stroke-width: 3.4; }
.vw-tools { position: relative; }
.vw-alt-t { font: 700 16px/1 var(--font-display); letter-spacing: .02em; }
.vw-alt[aria-expanded="true"] { background: #F2C0AB; }
/* The alt text panel: a speech bubble under its button, real text a person can select, read and copy. */
.vw-alt-panel { position: absolute; z-index: 5; top: calc(100% + 14px); right: 0; width: min(420px, calc(100vw - 24px)); padding: var(--sp3) var(--sp4) var(--sp3) var(--sp3);
  background: #FFFFFF; color: #0A0024; border: var(--edge); border-radius: 22px; box-shadow: 6px 6px 0 #88A31F; text-align: left; --focus: #56000E; }
.vw-alt-panel::before { content: ''; position: absolute; top: -12px; right: 182px; width: 20px; height: 20px; background: #FFFFFF; border-left: var(--edge); border-top: var(--edge); transform: rotate(45deg); }
.vw-alt-h { margin: 0 0 var(--sp1); font: 700 var(--t0)/1.2 var(--font-display); color: #56000E; }
.vw-alt-text { margin: 0; font-size: 18px; line-height: 1.5; user-select: text; -webkit-user-select: text; white-space: pre-wrap; }
.vw-alt-text:focus { outline: 3px solid #56000E; outline-offset: 4px; border-radius: 4px; }
.vw-alt-row { display: flex; align-items: center; gap: var(--sp3); margin-top: var(--sp3); }
.vw-alt-copy { min-height: 44px; padding: 6px 18px; }
.vw-alt-said { font-weight: 600; color: #4B5A0F; }
.vw-alt-x { position: absolute; top: 6px; right: 6px; display: grid; place-items: center; width: 44px; height: 44px; border: 0; border-radius: 50%; background: transparent; color: #56000E; cursor: pointer; }
.vw-alt-x .glyph { width: 18px; height: 18px; stroke-width: 3; }
.vw-alt-x:hover, .vw-alt-x:focus-visible { background: #F2C0AB; }
@media (max-width: 559px) { .vw-alt-panel { position: fixed; top: 72px; left: 12px; right: 12px; width: auto; } .vw-alt-panel::before { display: none; } }
/* Part C, item 2: a comic's page thumbnails, a row at the bottom; the current page has a Matcha ring. */
.vw-foot { display: grid; gap: var(--sp1); justify-items: center; }
.vw-thumbs { max-width: 100%; overflow-x: auto; padding: var(--sp2) var(--sp3) 0; }
.vw-thumbs ol { list-style: none; margin: 0; padding: 4px; display: flex; gap: var(--sp2); }
.vw-thumb { display: block; width: 56px; height: 72px; padding: 0; border: 2px solid #FEF1DF; border-radius: 8px; overflow: hidden; background: #FFFFFF; cursor: pointer; opacity: .75; transition: transform 200ms var(--spring), opacity 160ms ease; }
.vw-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vw-thumb:hover, .vw-thumb:focus-visible { opacity: 1; transform: translateY(-3px); }
.vw-thumb[aria-current="page"] { opacity: 1; border-color: #FEF1DF; box-shadow: 0 0 0 4px #88A31F; }
.vw-img { -webkit-user-drag: none; user-select: none; touch-action: none; }

/* Part D, About item 2: the visual description is a small disclosure under the Play/Pause button, closed by default. */
.intro-vid figcaption { margin-top: var(--sp2); }
.vid-desc summary { display: inline-flex; align-items: center; gap: var(--sp2); min-height: 44px; cursor: pointer; list-style: none; font: 600 16px/1.2 var(--font-display); color: #0A0024; }
.vid-desc summary::-webkit-details-marker { display: none; }
.vid-desc summary::before { content: ''; width: 9px; height: 9px; border-right: 3px solid currentColor; border-bottom: 3px solid currentColor; transform: rotate(-45deg); transition: transform 200ms ease; }
.vid-desc[open] summary::before { transform: rotate(45deg) translate(-2px, -2px); }
.vid-desc-t { text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 2px; }
.vid-desc p { margin: var(--sp1) 0 0; font-size: 16px; line-height: 1.5; max-width: 52ch; }
/* Part D, About item 4: gecko-me in front at the upper right, where her photo and the collage meet; the video is clean.
   Sizes are in container widths (cqw) so the corner holds at every width: the photo is 58% wide at 4:5 and the video
   rises 16% into it, so the video's top edge sits at about 61cqw. Gecko-me is 27cqw wide (36.5cqw tall); her top sits at 24cqw,
   so her feet just touch the tilted video's top-right corner. Her bubble's words sit above her in a small white bubble that overlaps the photo's
   top-right corner (foliage, clear of her face), pointing down at her. */
.about-media { isolation: isolate; container-type: inline-size; }
.gecko-me { position: absolute; z-index: 2; margin: 0; right: 1cqw; top: 24cqw; width: 27cqw; pointer-events: none; }
.gecko-me picture, .gecko-me img { display: block; width: 100%; height: auto; }
.gecko-me img { filter: drop-shadow(4px 4px 0 rgba(86, 0, 14, .22)); }
.gecko-say { position: absolute; right: 2cqw; bottom: calc(100% + 12px); width: max(176px, 46cqw); margin: 0; padding: 10px 14px; background: #FFFFFF; color: #56000E;
  border: var(--edge-sm); border-radius: 18px; font: 700 16px/1.3 var(--font-display); box-shadow: 3px 3px 0 #88A31F; pointer-events: auto; text-wrap: balance; }
@media (max-width: 767px) { .about-media { margin-top: 72px; } }
.gecko-say::after { content: ''; position: absolute; right: 14cqw; bottom: -9px; width: 14px; height: 14px; background: #FFFFFF; border-right: var(--edge-sm); border-bottom: var(--edge-sm); transform: rotate(45deg); }

/* Part D, About item 5: the pet cards are much smaller: body text 16 px, tight lists, smaller names and padding, so the
   four sit comfortably in one row on a desktop. Names and photos stay readable. */
.pet-card { padding: var(--sp2) var(--sp2) var(--sp3); gap: var(--sp1); }
.pet-name { font-size: var(--t2); margin: 0; }
.pet-kind { font-size: 16px; }
.pet-lists { gap: var(--sp2); font-size: 16px; line-height: 1.4; }
.pet-lists li { margin-bottom: 2px; }
.pl-h { font-size: 16px; margin: 0 0 2px; }
@media (min-width: 1024px) { .pet-grid { gap: var(--sp3); } }

/* Part D, About item 6: each FAQ question turns Matcha on hover and keyboard focus, and opens with a smooth expand
   (height plus fade, site.js); instant under Nap time and reduced motion. */
.faq-item summary { transition: background-color 160ms ease, color 160ms ease; border-radius: calc(var(--radius) - 3px); }
.faq-item summary:hover, .faq-item summary:focus-visible { background: #88A31F; color: #0A0024; }
.faq-item summary:focus-visible { outline: 3px solid #56000E; outline-offset: 3px; }
.faq-a { overflow: hidden; }
.faq-a p { margin: 0; padding: var(--sp3) var(--sp4) var(--sp4); }
.faq-item p { padding-top: var(--sp3); }

/* Part E: the Terms page, in the site's text-page style (Case Studies' head, a cream reading column). */
.terms-head { background: #F2C0AB; border-bottom: var(--edge); }
.terms-head .eyebrow { color: #56000E; }
.terms-toc ul { list-style: none; margin: var(--sp4) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp2); }
.terms-toc a { display: inline-flex; align-items: center; min-height: 44px; padding: 6px 16px; border: var(--edge-sm); border-radius: 999px; background: #FFFBF4; color: #0A0024; font: 600 16px/1.2 var(--font-display); text-decoration: none; transition: transform 260ms var(--spring); }
.terms-toc a:hover, .terms-toc a:focus-visible { transform: translateY(-3px) rotate(-2deg); background: #88A31F; }
.terms { background: #FEF1DF; }
.terms-wrap { max-width: 820px; }
.terms-sec { padding: 0; margin: 0 0 var(--sp6); scroll-margin-top: 96px; }
.terms-sec .h3 { color: #56000E; padding-bottom: var(--sp2); border-bottom: 3px dashed #F2C0AB; }
.terms-list { margin: 0 0 var(--sp3); padding-left: 1.2em; display: grid; gap: var(--sp2); }
.terms-list li::marker { color: #56000E; }
.terms-note { margin: var(--sp1) 0 0; padding-left: 1.2em; font-style: italic; }
.terms-end { padding: var(--sp5); background: #FFFFFF; border: var(--edge); border-radius: var(--radius); box-shadow: var(--hard-sm); }
.terms-end .lead { margin: 0; }
.foot-terms { color: #FEF1DF; font-weight: 700; white-space: nowrap; }

/* ---------- Revision 4 (Task 5006, Step 5006.rev.1): her review of revision 3, Thursday, October 15, 2026 ---------- */
/* Part A, Links item 1: the background is one of three options, never her doodle marks over red (too close to the
   site's own red ground). A: a big two-tone Matcha diamond checker (Matcha Ink at 28% on Matcha, about 1.4:1, so it
   stays quiet). B: flat Peach. C: big Peach dots on Cream. The card's line is Deep Wine Red on every option, and its
   hard shadow is Wine on the green option (a Matcha shadow would vanish there) and Matcha on the other two. */
.lk-page[data-bg="a"] { background-color: #88A31F; background-image: conic-gradient(from 45deg, rgba(75, 90, 15, .28) 25%, transparent 0 50%, rgba(75, 90, 15, .28) 0 75%, transparent 0); background-size: 192px 192px; }
.lk-page[data-bg="a"] .lk-card { box-shadow: 10px 10px 0 #56000E; }
.lk-page[data-bg="b"] { background: #F2C0AB; }
.lk-page[data-bg="c"] { background-color: #FEF1DF; background-image: radial-gradient(circle, #F2C0AB 30px, transparent 31px), radial-gradient(circle, #F2C0AB 30px, transparent 31px); background-size: 128px 128px; background-position: 0 0, 64px 64px; }
/* Part A, Links item 2: ONE rule for every button on the page. On mouse hover and on keyboard focus a button turns
   green or pink, whichever it is not: a White, Wine or Peach button turns Matcha #88A31F, a Matcha button turns Peach
   #F2C0AB. The label is Midnight #0A0024 on both (white on Matcha is 2.6:1 and fails, so a label never turns white). */
.lk:hover, .lk:focus-visible, .lk.lk-icon:hover, .lk.lk-icon:focus-visible, .lk-pins .lk.lk-kofi:hover, .lk-pins .lk.lk-kofi:focus-visible { background: #88A31F; color: #0A0024; }
.lk.lk-pin:not(.lk-kofi):hover, .lk.lk-pin:not(.lk-kofi):focus-visible { background: #F2C0AB; color: #0A0024; }
.lk:hover .lk-go, .lk:focus-visible .lk-go { color: #0A0024; }
.lk { transition: transform 260ms var(--spring), box-shadow 200ms ease, background-color 160ms ease, color 160ms ease; }
/* Part A, Links item 3: her gecko-me close-up, circle crop, inside a Matcha and Peach ring that turns once in 40 s.
   Only the ring turns, never her face. Nap time pauses it; reduced motion never starts it. */
.lk-av { position: relative; flex: none; display: grid; place-items: center; width: 120px; height: 120px; }
.lk-av-ring { position: absolute; inset: 0; border-radius: 50%; border: 3px solid #56000E; background: repeating-conic-gradient(#88A31F 0 15deg, #F2C0AB 15deg 30deg); animation: lk-ring 40s linear infinite; }
.lk-av picture { position: relative; display: block; width: 96px; height: 96px; }
.lk-avatar { display: block; width: 96px; height: 96px; border-radius: 50%; object-fit: cover; border: var(--edge); background: #FEF1DF; }
@keyframes lk-ring { to { transform: rotate(360deg); } }
html[data-motion="nap"] .lk-av-ring { animation: none; }
@media (prefers-reduced-motion: reduce) { .lk-av-ring { animation: none; } }
/* Part B, 404: the spinning green starry sparkle is gone (markup and rules). Her S squiggle, when it lands, is an img
   in the fizzle's place and size. A poke shows a random pose (site.js); the pose image keeps the fainted pose's box. */
img.ily-squiggle { object-fit: contain; }
/* Part C, the page doll on every page: under Nap time it shows her napping gecko (img.doll-nap) and never says
   "Psst!" on hover or focus. The two z's badge is gone: the napping art carries its own sleep. In the doll's lightbox a
   click inside the box no longer closes it (site.js); a small "Click outside to close" sits level with Close. */
.doll .doll-nap { display: none; animation: none; }
html[data-motion="nap"] .doll .doll-awake { display: none; }
html[data-motion="nap"] .doll .doll-nap { display: block; }
html[data-motion="nap"] .doll-say, html[data-motion="nap"] .doll-zz { display: none; }
.modal-foot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--sp2) var(--sp3); }
.modal-hint { margin: 0; font: 600 16px/1.3 var(--font-body); color: #0A0024; }
/* Part D, Home 1: the splash pictures stack in the art box and cross-fade (1.6 s) when site.js moves splash-on. Its
   own Pause slideshow sits at the art's top right. The hero words stay on the opaque Cream card, so their contrast is
   the card's on every picture: Midnight 18.16:1, Wine 13.45:1, Matcha Ink 6.81:1 on Cream. */
.hero-art .splash { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; opacity: 0; transition: opacity 1.6s ease; }
.hero-art .splash.splash-on { opacity: 1; }
.splash-tools { position: absolute; z-index: 3; top: var(--sp3); right: var(--sp3); }
.splash-tools .sec-toggle { background: #FFFBF4; color: #0A0024; min-height: 44px; padding: 6px 16px; font-size: 16px; }
@media (prefers-reduced-motion: reduce) { .hero-art .splash { transition: none; } }
/* Part D, Home 6: the Worlds row wraps, never scrolls (Decision recY3cDI1ibE1YFgd item 5): one card a row on a phone,
   two from 600 px, three from 1024 px. Each card shows a sentence or two about the world (span.world-about). */
.world-row { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: minmax(0, 1fr); gap: var(--sp4); overflow: visible; scroll-snap-type: none; padding: var(--sp2) var(--sp2) var(--sp4); }
@media (min-width: 600px) { .world-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .world-row { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp5); } }
.world-about { display: block; margin-top: var(--sp1); color: #0A0024; font-size: var(--t0); line-height: 1.45; }
/* Part E, Hire Me: tier columns by tier count, every service at one card scale. Below 768 px every list stacks (rule
   above). From 768 px: three tiers sit in three equal columns; four tiers two across, then three across from 1024 px
   (the fourth starts a row), so every service's cards are Service 1's width; one tier spans the row. Four across
   was tried and refused: a glued three-word tier name ("Minimal Character Animation") ran past a 200 px card. Every tier's picture is one modest height (180 px on a phone, 200 px from 768 px), cropped to
   fill for her art and contained for her own transparent pictures, so no card is taller than its words need.
   Case Studies (.cs-items) keeps one study a row at every width, by design: each study is a wide card whose picture
   sits beside its words from 1024 px (.cs-item 5fr 7fr); no rule forces it, it is the grid's single implicit column. */
@media (min-width: 768px) {
  .tier-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tier-list:has(> li:nth-child(3)):not(:has(> li:nth-child(4))) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .tier-list:not(:has(> li:nth-child(2))) { grid-template-columns: minmax(0, 1fr); } }
@media (min-width: 1024px) { .tier-list:has(> li:nth-child(4)) { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.tier-ex img, .tier-own img, .tier-ex img.own { aspect-ratio: auto; height: 180px; }
.tier-own picture { height: 180px; }
@media (min-width: 768px) { .tier-ex img, .tier-own img, .tier-ex img.own, .tier-own picture { height: 200px; } }
/* In the narrower multi-column band a glued tier name ("Partner Package (Pro)" at 768 px, "Minimal Character
   Animation" at 1024 px) ran up to 26 px past its card's line; the name steps down to 18 px there, the body size. */
@media (min-width: 768px) and (max-width: 1199px) { .tier-name { font-size: var(--t0); } }
/* Part E, Portfolio viewer: the alt text panel caps at 40% of the viewer's height and its words scroll inside it.
   Its title, Copy and the x stay put; the words take keyboard focus (tabindex 0) and scroll by arrow keys. */
.vw-alt-panel:not([hidden]) { display: flex; flex-direction: column; max-height: 40vh; }
.vw-alt-h, .vw-alt-row { flex: none; }
.vw-alt-text { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: var(--sp2); }
.vw-alt-text:focus, .vw-alt-text:focus-visible { outline-offset: -3px; }
@media (max-width: 559px) { .vw-alt-panel:not([hidden]) { max-height: 40vh; } }

/* =====================================================================================================================
   ART (Step 5033.art.1, Task 5033): Destiny's own art in the four slots, and her six phone findings
   ===================================================================================================================== */
/* Nap time stops ALL movement, not a list of it (her item 1; blueprint TPR-8644 producer b). Under data-motion="nap"
   no CSS animation or transition runs anywhere, the same rule base.css applies under prefers-reduced-motion. A hover
   or a tap still changes colour, shadow and position; it just happens at once. Scripted motion checks napping() itself
   (the testimonial rail, the arrow glide, the cross-fades, the splash, the FAQ, the 404 spin and confetti). A motion
   added later stops under Nap time with no new rule. */
html[data-motion="nap"] *, html[data-motion="nap"] *::before, html[data-motion="nap"] *::after { animation: none !important; transition: none !important; }

/* The page doll (her art test, approved Friday, October 16, 2026; her item 2). Her art is wide (560 x 378), so the box
   is too: 280 x 190 from 1024 px, right 14 px (her steer: about twice the old size). On a phone it is 120 x 81: it covers
   less of the text column while scrolling and its tap area stays well over 44 x 44 px. It is ALWAYS in front: z-index
   45 is above the sticky header (40) and every section; the duck rule is gone (Decision recAGjm9qnjRyDVXs clause 4). */
.doll { width: 120px; height: 81px; right: 6px; }
@media (min-width: 768px) { .doll { width: 150px; height: 104px; right: 10px; } }
@media (min-width: 1024px) { .doll { right: 14px; width: 280px; height: 190px; } }
.doll picture { display: block; width: 100%; height: 100%; }
.doll-say { right: 62%; bottom: 76%; }

/* 404 (her item 1, and the art test): five poses of different sizes sit on ONE fixed stage, the fainted pose's 471 x
   392 box, scaled to fit and standing on its bottom line, so a poke never makes the page jump. Her S squiggle is placed
   as she approved it: top right near the pet. Under Nap time and reduced motion a poke swaps the picture in place. */
.ily-img { aspect-ratio: 471 / 392; object-fit: contain; object-position: 50% 100%; }
img.ily-squiggle { width: clamp(30px, 9%, 46px); height: auto; right: 6%; top: 4%; }

/* Testimonials (her item 3, Home): the quote at the top, then the circle picture beside the name and title, then the
   green button. Each card is as tall as its own words (cards in the strip may differ), so no empty block sits above
   a short quote at any width. */
.tst { display: flex; flex-direction: column; align-items: stretch; gap: var(--sp3); grid-template-columns: none; grid-template-rows: none; }
.tst-track { align-items: flex-start; }
.tst-track .tst { height: auto; }
.tst blockquote, .tst figcaption { grid-column: auto; }
.tst figcaption { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp3); text-align: left; }
.tst-who { display: flex; align-items: center; gap: var(--sp3); }
.tst-who .avatar { flex: none; grid-row: auto; width: 56px; height: 56px; }
.tst-id { display: flex; flex-direction: column; min-width: 0; }
.tst-cs { align-self: flex-start; margin-top: 0; }
.tst::after { left: 40px; }

/* Support box (her item 4, Home): Ko-fi and Patreon side by side on one row, Follow for free on the next row under
   both, at every width from 320 px. The Follow button spans the two columns' width. */
.island .sup-row { display: grid; grid-template-columns: repeat(2, minmax(0, max-content)); justify-content: center; gap: var(--sp3); }
.island .sup-row .btn { justify-content: center; text-align: center; }
.island .sup-row .sup-follow { grid-column: 1 / -1; }

/* Portfolio on a phone (her item 6): the five medium buttons in ONE column, full width, stacked; the "Or by world" tags
   much smaller (14 px words, 34 px tall, tighter pills). Her ask outranks the 16 px floor here, and only here. */
@media (max-width: 767px) {
  .tabs { grid-template-columns: minmax(0, 1fr); }
  .tab { min-height: 52px; }
  .chips { gap: 6px; }
  .chips-label { font-size: 14px; width: 100%; }
  .chips .chip { min-height: 34px; padding: 4px 10px; font-size: 14px; border-width: 1.5px; }
}

/* =====================================================================================================================
   REVISION 5 (Step 5053.rev.1, Task 5053; Decision recYZbMEBSnMHHkC9). Every motion below is a CSS animation, so the
   Nap time rule above and base.css's reduced-motion rule stop it with no new rule; site.js also never starts it then.
   ===================================================================================================================== */
/* Part B: the water bucket. The bucket sits in the button in the button's own colour; the line under it is the
   role=status line, visible, in her hand font, and it keeps its height so the page does not jump on the first try. */
.ily-splash { display: inline-flex; align-items: center; gap: var(--sp2); }
.ily-bucket { display: inline-flex; flex: none; }
.nf-status { margin: 0; min-height: 2.6em; max-width: 420px; text-align: center; font-family: var(--font-hand); font-size: var(--t2); line-height: 1.3; color: #56000E; }
/* The splash: seven drops fall onto ILY pet, once per try, 700 ms. */
.ily-water { position: absolute; inset: -14% 8% auto; height: 60%; pointer-events: none; }
.ily-water i { position: absolute; top: 0; width: 14px; height: 20px; border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%; background: #FFFFFF; border: 2px solid #0A0024; opacity: 0; }
.ily-water i:nth-child(1) { left: 6%; } .ily-water i:nth-child(2) { left: 20%; --dd: 60ms; } .ily-water i:nth-child(3) { left: 34%; --dd: 20ms; }
.ily-water i:nth-child(4) { left: 50%; --dd: 90ms; } .ily-water i:nth-child(5) { left: 64%; --dd: 40ms; } .ily-water i:nth-child(6) { left: 78%; --dd: 110ms; }
.ily-water i:nth-child(7) { left: 90%; --dd: 70ms; }
.ily.splashed .ily-water i { animation: ily-drop 700ms cubic-bezier(.5, 0, .8, .6) var(--dd, 0ms) both; }
@keyframes ily-drop { 0% { opacity: 0; transform: translateY(-30px); } 15% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; transform: translateY(150px) scaleY(.6); } }
/* The reward heading takes focus on the wake (tabindex -1), so it reads as the next thing; her art fills the box. */
.nf-prize-h { margin: 0 0 var(--sp2); }
.nf-prize-h:focus-visible { outline: 3px solid #56000E; outline-offset: 4px; border-radius: 6px; }
.nf-reward-art { display: block; width: 100%; height: auto; border-radius: 16px; }

/* Part C: the dizzy doll. Hidden until site.js sets data-dizzy; then it is the ONLY doll picture, napping or not, until
   the page reloads. Its "Psst!" line is DIZZY.say, shown like the awake doll's and never under Nap time. */
.doll .doll-dizzy { display: none; }
html[data-motion] .doll[data-dizzy="true"] .doll-awake, html[data-motion] .doll[data-dizzy="true"] .doll-nap { display: none; }
html[data-motion] .doll[data-dizzy="true"] .doll-dizzy { display: block; }
.doll-say-dizzy { display: none; white-space: nowrap; }
.doll[data-dizzy="true"] .doll-say:not(.doll-say-dizzy) { display: none; }
.doll[data-dizzy="true"] .doll-say-dizzy { display: block; }
html[data-motion="nap"] .doll[data-dizzy="true"] .doll-say-dizzy { display: none; }

/* Part D: each pet picture in the gecko box is a button that zooms it in the viewer. A small + badge says so; hover and
   keyboard focus lift the badge's colour, and the focus ring sits on the picture's own rounded frame. */
.lb-zoom { position: relative; display: block; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; border-radius: 12px; }
.lb-zoom:focus-visible { outline: 3px solid #0A0024; outline-offset: 3px; }
.lb-zoom img { display: block; }
.lb-zoom-ico { position: absolute; right: 6px; bottom: 6px; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 50%; background: #FFFFFF; border: 2px solid #56000E; color: #56000E; }
.lb-zoom-ico .glyph { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; }
.lb-zoom:hover .lb-zoom-ico, .lb-zoom:focus-visible .lb-zoom-ico { background: #88A31F; color: #0A0024; border-color: #0A0024; }

/* The moved page (hire-me.html): one line and one button, centred. */
.page-moved .moved { min-height: 60vh; display: grid; place-content: center; text-align: center; gap: var(--sp3); }

/* Builder port fixes, Step 4701.rev.2 (task recd42u0G1mGBjayg), found by the seven-width lines and overflow checks
   (320, 390, 768, 900, 1024, 1200, 1440). Revision 3 was measured for page width at those widths, not for every line
   holding two words or for content inside its own box, so these carried through. Each rule names what it fixed. */
/* 768 to 1023 px: the cards were 320 px with the avatar column beside the quote, so quotes broke one word a line
   ("her", "sign"). The cards take their 1024 px width from 768. */
@media (min-width: 768px) { .tst-track > li { width: 460px; } }
/* Short titles of three or four words break evenly, so the last line is never one word ("Deaf Artists on / Bluesky",
   "Follow for free / updates", "communicating / with you!"). */
.res-t, .role-t, .faq-q, .svc-jump a, .btn { text-wrap: balance; }
/* 1024 to 1279 px: "Rough, lineart and color animation" in a 217 px role box left "and" alone. */
@media (min-width: 1024px) and (max-width: 1279px) { .role-t { padding: 4px 10px; font-size: var(--t0); } }
@media (max-width: 379px) {
  /* The hero kept its 44.8 px heading (.hero-card .display outranks revision 3's .display step) and stranded "animate"
     and "and". */
  .hero-card .display { font-size: 32px; max-width: none; }
  .ig-handle { font-size: 18px; }
  .faq-item summary { padding-left: var(--sp3); padding-right: var(--sp3); } .faq-q { font-size: 19px; }
  .svc-jump a { font-size: 16px; padding-left: 12px; padding-right: 12px; }
  /* "Download the Secret ASL font" ran 6 px out of its 117 px picture box. */
  .lk-pins .lk.has-pic:not(.lk-kofi) .lk-t { font-size: 16px; }
  /* Case study 3's glued "Theatre costume renderings" (276 px) widened its card's one auto track 26 px past the card. */
  .cs-item { grid-template-columns: minmax(0, 1fr); } .cs-sub { font-size: 16px; }
}
/* The testimonial arrows (the live session's check of 4f103040, Tuesday, October 13, 2026 at 4:35 PM EDT): at 1440 px
   the < sat on the end of Cindy Oswald's quote, because the arrows were drawn over the strip and the mask only fades it.
   From 768 px the strip stops short of each side by the arrow's width plus a gap, so each arrow has its own gutter and
   no card passes under it. Below 768 px the arrows already sit under the strip. */
@media (min-width: 768px) { .tst-vp { padding-left: calc(52px + 2 * var(--sp2)); padding-right: calc(52px + 2 * var(--sp2)); } }
@media (min-width: 1024px) { .tst-vp { padding-left: calc(52px + var(--sp4) + var(--sp2)); padding-right: calc(52px + var(--sp4) + var(--sp2)); } }

/* Port, Step 5053.rev.2 (task reckkVCcfCEjD44xG): her dizzy doll and its swirls (her asks of Friday, October 16, 2026).
   Her dizzy gecko sits up, so it is TALLER than the wide awake and napping art. It keeps the awake art's pixel scale (560
   source px = the doll box's width: 120, 150 or 280 px) and takes its own height from the file, anchored bottom-right,
   so it grows upward while dizzy: 280 x 300 from 1024 px. Two of her swirls turn slowly over the swollen head, in
   opposite directions; the Nap time rule above and base.css's reduced-motion rule stop them where they sit. */
.doll[data-dizzy="true"] { height: auto; }
.doll[data-dizzy="true"] .doll-dizzy, .doll[data-dizzy="true"] .doll-dizzy img { height: auto; }
.doll-swirls { display: none; position: absolute; left: 0; right: 0; top: -19%; height: 24%; pointer-events: none; }
.doll[data-dizzy="true"] .doll-swirls { display: block; }
.doll-swirls .doll-swirl { position: absolute; top: 0; left: 20%; width: 22.3%; height: auto; animation: doll-swirl 5s linear infinite; }
.doll-swirls .doll-swirl + .doll-swirl { left: 56%; animation-duration: 5.5s; animation-direction: reverse; }
@keyframes doll-swirl { to { transform: rotate(360deg); } }
/* "Work with me" is two words longer than "Hire Me": the header button keeps it on one line (the lines check found
   "Work / with me" at 1024 px). */
.btn-hire { white-space: nowrap; }
/* Her longer pop-up hint (revision 5) no longer fits beside Close at 390 px (256 + 24 + 87 px in 288), so it wrapped under
   it; it now takes the room Close leaves and wraps there, level with Close as revision 4 asked. */
.modal-foot .modal-hint { flex: 1 1 0; min-width: 0; }

/* =====================================================================================================================
   TIMELINE (Step 5061.tl.1, Task 5061): her career timeline on About. Palette only: wine, cream, white, matcha, peach,
   ink. No new motion: nothing here animates or transitions, so Nap time and reduced motion have nothing to stop. The
   GIF's still swap is site.js's data-still rule; the video never autoplays.
   ===================================================================================================================== */
.tl-wrap { position: relative; margin-top: var(--sp6); }
/* REVISION 7 (Task 5575, her sketch): the line is HER drawn line (assets/about/timeline/line-v.png, src/tl-assets.py
   --rev7: her stroke with its slow drift taken out and its top tapered to nothing), stretched down the whole run of
   beats as a mask in Wine, so it is one seamless stroke at any height. It starts 64 px above the first knot (the taper)
   and runs on into the upright stroke of her "To be continued" art, which continues it (.tl-end). --lx is the line's
   centre; the ending is placed so its upright stroke sits on it. */
.tl-run { --lx: 18px; --lw: 30px; position: relative; padding-top: 64px; }
.tl-line { position: absolute; top: 0; bottom: -18px; left: calc(var(--lx) - var(--lw) / 2); width: var(--lw); background: #56000E; z-index: 0;
  -webkit-mask: url(about/timeline/line-v.png) center top / 100% 100% no-repeat; mask: url(about/timeline/line-v.png) center top / 100% 100% no-repeat; }
.tl-beats { list-style: none; margin: 0; padding: 0; position: relative; }
/* A beat: the year by the knot, then ONE unit (pictures, then title and words). On a phone everything sits right of the line. */
.tl-beat { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); padding: 0 0 var(--sp4) calc(var(--lx) + 26px); }
.tl-beat:last-child { padding-bottom: var(--sp4); }
/* the knot on the line: a hand-drawn blob, not a perfect circle, level with the year */
.tl-beat::before { content: ''; position: absolute; left: calc(var(--lx) - 11px); top: 4px; width: 22px; height: 20px; z-index: 1; border-radius: 52% 48% 55% 45% / 46% 54% 48% 52%;
  background: #88A31F; border: 3px solid #56000E; transform: rotate(-8deg); }
.tl-year { font-family: var(--font-hand); font-size: var(--t2); line-height: 1; color: #56000E; margin: 0 0 var(--sp2); }
.tl-unit { min-width: 0; }
.tl-title { font-size: var(--t1); line-height: 1.25; color: #0A0024; margin: 0 0 var(--sp1); }
.tl-text { margin-top: 12px; }
.tl-text p { font-size: 16px; line-height: 1.5; margin: 0; }
.tl-text .tl-glue { white-space: nowrap; }
.tl-text a { color: #56000E; font-weight: 600; text-decoration-thickness: 2px; text-underline-offset: 3px; }
/* Her pictures as a small photo-album cluster, like her sketch: one height per cluster (--ph), each next mat overlapping
   the last a little, tilted, wrapping when the column runs out. White mats, her doc's words as the handwritten caption. */
.tl-pics { --ph: 128px; display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px 0; padding: 0 4px; }
.tl-pics.n-1 { --ph: 176px; }
.tl-pic { position: relative; margin: 0; background: #FFFFFF; padding: 6px 6px 4px; border: var(--edge-sm); border-radius: 6px; box-shadow: var(--hard-xs);
  transform: rotate(var(--tilt, 0deg)); max-width: 100%; flex: none; }
.tl-pic + .tl-pic { margin-left: -12px; margin-top: 14px; }
.tl-pic:nth-child(2) { z-index: 1; } .tl-pic:nth-child(3) { z-index: 2; }
.tl-pic img, .tl-pic video { display: block; height: var(--ph); width: auto; max-width: 100%; object-fit: contain; border-radius: 2px; }
.tl-pic.tl-small img { height: auto; width: 150px; }
.tl-pic.tl-video video { height: calc(var(--ph) * 1.6); background: #56000E; }
.tl-cap { font-family: var(--font-hand); font-size: 16px; line-height: 1.15; color: #56000E; text-align: center; padding-top: 4px; max-width: 24ch; margin: 0 auto; }
/* a slot she has not filled yet: a labelled stand-in at the picture's own shape */
.tl-stand-box { display: grid; place-items: center; height: var(--ph); background: #FEF1DF; border: 2px dashed #56000E; border-radius: 2px; padding: 8px; text-align: center; font-size: 16px; line-height: 1.3; }
/* Her ending. Its upright stroke (at --stem of its width) sits on the line's centre, so the line runs on into the arrow;
   it overlaps the line's last 18 px, so there is no gap and no cut. alt says its words. */
.tl-end { --ew: min(320px, calc(100% - var(--lx))); position: relative; z-index: 1; width: var(--ew); margin: 0 0 0 calc(var(--lx) - var(--ew) * var(--stem)); }
.tl-end img { display: block; width: 100%; height: auto; }
/* Awards and talks (her awards item): no hand-drawn line under them, no box, border, shadow or hover on any item. ONE
   ordered row of small logos, each above its name; talks keep their own row of the same form. Under 560 px the row
   WRAPS (two a line, the last one centred); it never scrolls. Nothing in it is a link or a button. */
.tl-shelf { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp6); margin-top: var(--sp7); padding: var(--sp5) var(--sp4); background: #FFFBF4; border: var(--edge); border-radius: var(--radius); }
.shelf-group { min-width: 0; }
.shelf-h { font-size: var(--t2); color: #56000E; margin-bottom: var(--sp4); text-align: center; }
.aw-row { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp4) var(--sp3); }
.aw { flex: 0 1 calc(50% - var(--sp3)); min-width: 0; display: flex; flex-direction: column; align-items: center; gap: var(--sp2); text-align: center; cursor: default; }
.aw-logo { display: block; width: 64px; height: 64px; flex: none; border-radius: 50%; overflow: hidden; }
.aw-logo img { display: block; width: 100%; height: 100%; }
.aw-mark { display: grid; place-items: center; background: #56000E; color: #FEF1DF; font: 700 18px/1 var(--font-display); letter-spacing: .04em; }
.aw-t { font-size: 16px; line-height: 1.35; overflow-wrap: break-word; }
.aw-t strong { display: block; font-family: var(--font-display); font-weight: 700; color: #56000E; }
.aw-d { display: block; color: #0A0024; }
.tl-sep { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@media (max-width: 767px) {
  .shelf-h { font-size: var(--t1); } .tl-shelf { padding: var(--sp4) var(--sp3); }
}
@media (max-width: 379px) { .tl-title { font-size: 19px; } .tl-text .tl-glue { white-space: normal; } .tl-text a { overflow-wrap: anywhere; } .tl-pics { --ph: 110px; } .tl-pics.n-1 { --ph: 150px; } }
@media (min-width: 560px) { .aw { flex-basis: calc(33.333% - var(--sp3)); } }
/* 768 to 1023 px: one side, as on a phone, with a wider column; the year and the cluster share the first row. */
@media (min-width: 768px) {
  .tl-run { --lw: 36px; --lx: 22px; }
  .tl-pics { --ph: 116px; } .tl-pics.n-1 { --ph: 148px; }
  .tl-shelf { padding: var(--sp6); }
  .aw { flex-basis: calc(20% - var(--sp3)); }
  .aw-logo { width: 72px; height: 72px; }
  .tl-end { --ew: 400px; }
@media (min-width: 1024px) {
  /* Her sketch: the line runs down the middle; the year sits by the knot on one side and the unit on the other, sides
     alternating, so a beat's words only ever sit under its own pictures and across the line from nothing but a year. */
  .tl-run { --lx: 50%; --lw: 40px; }
  .tl-beat { grid-template-columns: minmax(0, 1fr) 64px minmax(0, 1fr); padding: 0 0 var(--sp4); align-items: start; }
  .tl-beat::before { left: 50%; top: 22px; margin-left: -11px; }
  .tl-beat > .tl-year { grid-column: 1; grid-row: 1; justify-self: end; margin: 18px 0 0; font-size: var(--t3); }
  .tl-beat > .tl-unit { grid-column: 3; grid-row: 1; max-width: 560px; }
  .tl-beat:nth-child(even) > .tl-year { grid-column: 3; justify-self: start; }
  .tl-beat:nth-child(even) > .tl-unit { grid-column: 1; justify-self: end; }
  .tl-beat:nth-child(even) .tl-pics { justify-content: flex-end; }
  .tl-pics { --ph: 116px; } .tl-pics.n-1 { --ph: 148px; }
  .tl-end { --ew: 440px; margin-left: calc(50% - var(--ew) * var(--stem)); }
}
}

/* Builder port fix, Step 5575.rev.2 (r4-tl-browser's layout check): the line's --lx and --lw live on .tl-run, but her
   ending (.tl-end) is .tl-run's sibling, so below 1024 px var(--lx) was undefined there: the ending fell back to the
   full column width with no margin, its upright stroke 3 px (390) and 5 px (768) off the line. The same values on
   .tl-wrap reach both, so the stroke sits on the line's centre at every width, as spec TPR-9765 Part A says. The
   reference tree (ec2f1739) has the same gap; from 1024 px its 50% rule already holds. */
.tl-wrap { --lx: 18px; --lw: 30px; }
@media (min-width: 768px) { .tl-wrap { --lx: 22px; --lw: 36px; } }
@media (min-width: 1024px) { .tl-wrap { --lx: 50%; --lw: 40px; } }
/* Builder port fix, Step 5575.rev.2 (r4-browser's every-line check, her Global 9 rule: no line holds one word). Glued, her
   longest name, "University of Pittsburgh", is 172 px at 16 px and must sit on one line, so an item needs at least
   176 px. The spec's two a line on a phone gives about 145 px at 390, and its five across from 768 px about 120 to 160 px
   below 1200, so names broke as "University of / Pittsburgh". Columns by measured width instead: one a line below
   560 px, two from 560, three from 768, four from 1024 and five from 1200, so 1440 keeps one line of five. The rows
   still wrap and never scroll. */
.aw { flex-basis: 100%; }
@media (min-width: 560px) { .aw { flex-basis: calc(50% - var(--sp3)); } }
@media (min-width: 768px) { .aw { flex-basis: calc(33.333% - var(--sp3)); } }
@media (min-width: 1024px) { .aw { flex-basis: calc(25% - var(--sp3)); } }
@media (min-width: 1200px) { .aw { flex-basis: calc(20% - var(--sp3)); } }
/* 320 to 379 px (the same check): the 2024 beat's "Ko-fi: ko-fi.com/s/502b3ab8a8" is 246 px at 16 px; with the beat 4 px
   nearer the line its box is 248 px, so the glue holds and the address is never alone or broken. "Select awards &
   recognition" left "& recognition" alone on a line at 22 px; at 19 px it fits. Both are Step 5061.tl.2's fixes, kept. */
@media (max-width: 379px) {
  .tl-beat { padding-left: calc(var(--lx) + 22px); }
  .tl-text .tl-glue { white-space: nowrap; } .tl-text a { overflow-wrap: normal; }
  .shelf-h { font-size: 19px; }
}

/* REVISION 7, the rest (Task 5575). */
/* The case study "Client:" line in matcha (her case study item). Her #88A31F measures 2.87:1 on the white index card and
   1.77:1 on the peach study title band, under AA's 4.5:1 for this 18 px text, so each ground takes the nearest matcha
   that passes (her hue and saturation, lightness lowered): 4.57:1 and 4.59:1 (contrast.txt, revision 7). */
.cs-item .cs-client { color: #697E18; }
.cs-head .cs-client { color: #4C5B11; }
/* Home testimonials (Task 5146 Addendum): her clients' pictures in the circle, and every quote marked as an excerpt. */
.avatar.av-pic { padding: 0; overflow: hidden; background: #FEF1DF; }
.avatar.av-pic img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.tst-cut { color: #56000E; font-weight: 700; letter-spacing: .06em; }
/* the closing mark stands a little apart, so "creativity.…" reads as a sentence and then the cut */
.tst-excerpt blockquote p > .tst-cut:last-child { margin-left: .2em; }
/* the opening mark and its quote sign hang into the card's padding (hanging punctuation), so the first line keeps the
   width it had before the mark and a short quote wraps where it did ("thorough," never stands alone at 390 px) */
.tst-excerpt blockquote p > .tst-open { margin-left: -1.05em; }
/* 404 hearts (her 404 item): every press bursts her hearts out of ILY pet. aria-hidden, removed when they land; site.js
   never makes them under Nap time or reduced motion, and the Nap time rule would stop them anyway. */
.ily { position: relative; }
.ily-heart { position: absolute; left: 50%; top: 45%; width: 38px; height: auto; pointer-events: none; z-index: 3; opacity: 0;
  animation: ily-heart 900ms cubic-bezier(.2, .7, .3, 1) var(--hd, 0ms) both; }
@keyframes ily-heart { 0% { opacity: 0; transform: translate(-50%, -50%) scale(.3) rotate(0deg); } 15% { opacity: 1; }
  70% { opacity: 1; } 100% { opacity: 0; transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(var(--hs, 1)) rotate(var(--rot)); } }
/* While angry, ILY pet vibrates very fast and small (her words), for as long as it is angry. */
.nf-stage[data-angry="true"] .ily-img { animation: ily-buzz 70ms linear infinite; }
@keyframes ily-buzz { 0% { transform: translate(0, 0) rotate(0); } 25% { transform: translate(-2px, 1px) rotate(-.8deg); } 50% { transform: translate(2px, -1px) rotate(.8deg); } 75% { transform: translate(-1px, -1px) rotate(-.4deg); } 100% { transform: translate(1px, 1px) rotate(.4deg); } }
/* Links: the Ko-fi widget stand-in under every button, the shape of Ko-fi's panel (cup, heading, note field, button),
   with no amounts (her no-prices rule). */
.kofi-widget { margin-top: var(--sp5); background: #FFFFFF; border: var(--edge-sm); border-radius: 16px; padding: var(--sp4); display: grid; gap: var(--sp3); text-align: center; }
.kofi-w-h { margin: 0; display: flex; align-items: center; justify-content: center; gap: var(--sp2); font: 700 var(--t1)/1.2 var(--font-display); color: #56000E; }
.kofi-w-cup { display: inline-flex; width: 36px; height: 36px; }
.kofi-w-cup svg { width: 100%; height: 100%; }
.kofi-w-p { margin: 0; font-size: 16px; }
.kofi-w-note { display: block; text-align: left; padding: 10px 14px; border: 2px solid #C9B9A8; border-radius: 10px; color: #6B5D52; font-size: 16px; }
.kofi-w-btn { display: inline-flex; justify-content: center; align-items: center; min-height: 48px; padding: 10px 24px; border-radius: 999px; background: #F2C0AB; color: #56000E; border: 3px solid #56000E; font: 700 var(--t0)/1.2 var(--font-display); text-decoration: none; }
.kofi-w-btn:hover, .kofi-w-btn:focus-visible { background: #88A31F; color: #0A0024; }

/* =====================================================================================================================
   REVISION 6 (Step 5146.rev.1, Task 5146; Decision recetOx9rQ96NeUl8). Destiny's review of revision 5, Saturday, October
   17, 2026. Every motion below is a CSS animation that site.js starts only when neither Nap time nor reduced motion is on,
   and the Nap time rule above and base.css's reduced-motion rule stop it anyway. Port, Step 5146.rev.2: the reference's
   Part A (her dizzy doll and swirls) is already the "Port, Step 5053.rev.2" section above, so it is not repeated here.
   ===================================================================================================================== */
/* Part B: "Meet my crew" columns live in base.css (1, 2 from 560 px, 4 from 1024 px, never 3). A card may not grow
   past its track. */
.pet-card { min-width: 0; }
/* Four in one row at 1024 px left each card 217 px, and her three-word lines are glued (no line of one word), so
   "Accidentally gulping water" (207 px at 16 px) ran 15 px past the card. Until 1200 px the lists are 15 px with a
   tighter indent and the cards a tighter gap; from 1200 px they are revision 5's again. */
@media (min-width: 1024px) and (max-width: 1199px) {
  .pet-grid { gap: 6px; } .pet-lists ul { padding-left: 1.1ch; } .pet-card { padding-left: 4px; padding-right: 4px; } }
/* Step 4453.site.4: the day-one site keeps the 16 px floor at every check width (spec TPR-10477), and /r4/'s 15 px
   here was under it at 1024 to 1199 px (its text-size check ran at 390 and 1440 only). The lists stay 16 px; the room
   comes from a 6 px gap, a 1.1ch indent and 4 px card sides (measured: no overflow, no lone word at 1024, 1100, 1199). */

/* Part C: the 404. A miss shakes the fainted pose once (C2); each press after the wake cheers once (C4): a hop with a
   squash, 600 ms. */
.ily.twitch .ily-img { animation: ily-twitch 650ms ease-in-out 1; }
.ily.cheer .ily-img { animation: ily-cheer 600ms var(--spring) 1; }
@keyframes ily-cheer { 0% { transform: none; } 25% { transform: translateY(-28px) rotate(-6deg) scale(1.04); } 55% { transform: translateY(0) scale(1.08, .92); } 75% { transform: translateY(-8px) rotate(4deg); } 100% { transform: none; } }
/* C5: the limit. The button's two halves (span.ily-shard, copies of the button, aria-hidden) split down the middle,
   tip and fall away in 700 ms while the real button is already hidden. site.js holds the slot at the button's size
   for the fall, so the caption does not jump up under the halves; once they are gone it closes. */
.ily-splash-slot { position: relative; display: flex; justify-content: center; }
.ily-shard { position: absolute; pointer-events: none; z-index: 2; }
.ily-shard .ily-splash { width: 100%; height: 100%; margin: 0; white-space: nowrap; justify-content: center; }
.ily-shard-l { clip-path: inset(-20px 50% -20px -20px); animation: ily-shard-l 700ms cubic-bezier(.4, 0, .9, .5) both; transform-origin: 30% 100%; }
.ily-shard-r { clip-path: inset(-20px -20px -20px 50%); animation: ily-shard-r 700ms cubic-bezier(.4, 0, .9, .5) both; transform-origin: 70% 100%; }
@keyframes ily-shard-l { 0% { transform: none; opacity: 1; } 20% { transform: translateX(-6px) rotate(-6deg); } 100% { transform: translate(-60px, 120px) rotate(-40deg); opacity: 0; } }
@keyframes ily-shard-r { 0% { transform: none; opacity: 1; } 20% { transform: translateX(6px) rotate(6deg); } 100% { transform: translate(60px, 120px) rotate(40deg); opacity: 0; } }
/* The mad caption IS the status line, larger and bold in Wine; it takes focus when the button goes. Port: her caption
   is two lines (a \n in data.mjs ILY_ANGRY.mad), kept by pre-line. */
.nf-status.mad { font: 700 var(--t3)/1.2 var(--font-display); color: #56000E; letter-spacing: .01em; white-space: pre-line; }
.nf-status:focus { outline: none; }
.nf-status:focus-visible { outline: 3px solid #56000E; outline-offset: 4px; border-radius: 6px; }
/* Port (TPR-9072): visually hidden text a screen reader still reads, for the words beside her aria-hidden ">:C". */
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }


/* ==========================================================================
   CASE STUDY PAGES (Step 5159.cs.1, Task 5159, Decision recwDH4ifReaT51TZ). The index keeps the Case Studies look
   (.cs-head, .cs-list, .cs-item); a finished card shows its first picture whole-colour and links to its page. Each page
   (case-study-<slug>.html) reuses .cs-head for its title band, then: the story in one white card (.csp-story), her
   pictures as photo-album mats like the timeline's (.csp-fig, each a button into the pop-up viewer), the videos, the
   products, the credit line, the testimonial (.csp-quote, the .tst card grown up) and the call to action.
   ========================================================================== */
.cs-done .cs-art-real { display: block; background: #FFFBF4; }
.cs-done .cs-art-real img { opacity: 1; object-position: 50% 0; }
.cs-summary { margin: var(--sp3) 0 var(--sp4); }
.cs-read { margin-top: 0; }
.csp-head .display { margin-bottom: 0; }
.csp-head .lead { margin-top: var(--sp3); max-width: 62ch; }
.csp-back { margin: 0 0 var(--sp3); font-weight: 600; }
.csp-back a, .csp-back-link { color: #56000E; text-underline-offset: 3px; }
.csp-back a::before { content: "\2190\00a0"; }
.csp-body { background: #FEF1DF; padding: var(--sp6) 0 var(--sp7); }
.csp-story { max-width: 780px; margin: 0 auto; background: #FFFFFF; border: var(--edge); border-radius: var(--radius); box-shadow: var(--hard); padding: var(--sp5); }
.csp-part + .csp-part { margin-top: var(--sp5); padding-top: var(--sp5); border-top: var(--edge-dash); }
.csp-h { margin: 0 0 var(--sp3); font: 700 var(--t3)/1.15 var(--font-display); color: #56000E; }
.csp-story p { margin: 0 0 var(--sp3); max-width: 68ch; }
.csp-story p:last-child, .csp-story .csp-list:last-child { margin-bottom: 0; }
.csp-list { margin: 0 0 var(--sp3); padding: 0; list-style: none; display: grid; gap: var(--sp2); }
.csp-list li { position: relative; padding-left: 28px; }
.csp-list li::before { content: ""; position: absolute; left: 4px; top: .55em; width: 12px; height: 12px; border-radius: 50%; background: #88A31F; border: 2px solid #56000E; }
.csp-gallery { list-style: none; margin: var(--sp7) 0 0; padding: 0; display: grid; gap: var(--sp5) var(--sp4); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 560px) { .csp-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .csp-gallery { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.csp-fig { margin: 0; background: #FFFFFF; padding: 10px 10px 8px; border: var(--edge-sm); border-radius: 6px; box-shadow: var(--hard-sm); transform: rotate(var(--tilt, 0deg)); transition: transform var(--dur) ease; }
.csp-fig:hover, .csp-fig:focus-within { transform: none; }
.csp-zoom { display: block; width: 100%; padding: 0; border: 0; background: #FFFBF4; border-radius: 2px; cursor: zoom-in; }
.csp-zoom:focus-visible { outline: 3px solid #56000E; outline-offset: 3px; }
.csp-zoom img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: contain; }
.csp-cap { font-family: var(--font-hand); font-size: var(--t1); line-height: 1.2; color: #56000E; text-align: center; padding: 8px 4px 0; }
.csp-videos { margin: var(--sp7) auto 0; max-width: 860px; display: grid; gap: var(--sp5); grid-template-columns: minmax(0, 1fr); justify-items: center; }
@media (min-width: 768px) { .csp-videos { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.csp-vid { --tilt: 0deg; width: 100%; max-width: 380px; }
.csp-vid video { display: block; width: 100%; height: auto; max-height: 640px; background: #56000E; border-radius: 2px; }
.csp-products { max-width: 780px; margin: var(--sp7) auto 0; padding: var(--sp4) var(--sp5); list-style: none; display: grid; gap: var(--sp3); background: #FFFFFF; border: var(--edge-sm); border-radius: var(--radius); box-shadow: var(--hard-sm); }
.csp-products li { position: relative; padding-left: 28px; }
.csp-products li::before { content: ""; position: absolute; left: 4px; top: .55em; width: 12px; height: 12px; border-radius: 50%; background: #F2C0AB; border: 2px solid #56000E; }
.csp-products a { color: #56000E; font-weight: 700; text-underline-offset: 3px; }
.csp-credit { max-width: 780px; margin: var(--sp5) auto 0; text-align: center; font-style: italic; }
.csp-quote { position: relative; max-width: 860px; margin: var(--sp7) auto 0; background: #FFFFFF; border: var(--edge); border-radius: 28px; box-shadow: var(--hard); padding: var(--sp6) var(--sp5) var(--sp5); }
.csp-quote::before { content: "\201C"; position: absolute; top: -34px; left: 24px; font: 700 96px/1 var(--font-display); color: #F2C0AB; -webkit-text-stroke: 3px #56000E; }
.csp-quote blockquote { margin: 0; font-size: var(--t1); }
.csp-quote blockquote p { margin: 0 0 var(--sp3); }
.csp-quote-intro { margin: 0 0 var(--sp2); font-weight: 600; }
.csp-quote figcaption { margin-top: var(--sp3); font: 700 var(--t1)/1.3 var(--font-display); color: #56000E; }
.csp-next { margin: var(--sp7) 0 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--sp3) var(--sp5); }
.csp-back-link { font-weight: 600; }
.csp-story, .csp-quote, .csp-products, .csp-gallery > li { min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 559px) {
  .csp-story, .csp-quote, .csp-products { padding-left: var(--sp3); padding-right: var(--sp3); }
  .csp-h { font-size: var(--t2); }
}
/* A finished study's title: "<name>: <what>" is one heading, the colon kept for screen readers and hidden, the part after
   it a line of its own in the .cs-sub face, its first letter raised so the words stay the Writer's. */
.csp-title .csp-colon { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.csp-title .cs-sub { display: block; }
.csp-title .cs-sub::first-letter { text-transform: uppercase; }
@media (min-width: 1024px) { .csp-gallery.n-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* Her three-word names are glued ("Deaf Spotlight 2024" never wraps), so below 560 px the title scales with the
   screen: 10vw holds the longest name inside a 320 px screen's 288 px column. */
@media (max-width: 559px) { .csp-head .display { font-size: min(var(--t5), 10vw); } }
/* Builder port fix (Step 5159.cs.2): at 390 px the Deaf Spotlight card's one auto track grew to its title's min-content
   and ran 26 px past the card (r4-browser's every-width overflow check). The port's 379 px fix above, at every width
   below the 1024 px two-column layout. */
@media (max-width: 1023px) { .cs-item { grid-template-columns: minmax(0, 1fr); } }
/* Builder port fix (Step 5159.cs.2 round 2, QA TPR-9770 finding 1): at 320 px the story card's text column is 250 px, and
   two of her glued chunks are wider than it at 18 px: the list item "corrective design feedback" (237 px in a 222 px
   item) and "Ko-fi: ko-fi.com/s/502b3ab8a8" (268 px), so overflow-wrap broke a word inside them. Below 360 px the story
   text is 16 px, the text floor; both chunks then fit whole and every line keeps two words. */
@media (max-width: 359px) { .csp-story { font-size: 16px; } }


/* ---------- Step 4453.site.4: the day-one additions (spec TPR-10477). Tokens only; nothing above is changed. ---------- */
/* The footer's support row: Ko-fi and Patreon on one row, Follow for free updates under both (her Task 5033 item 4),
   in the island's colours, since the footer is Wine too. */
.foot-support { padding-top: var(--sp5); padding-bottom: var(--sp4); }
.foot-sup { display: grid; grid-template-columns: repeat(2, minmax(0, max-content)); justify-content: start; gap: var(--sp3); margin: 0; }
.foot-sup .btn { justify-content: center; text-align: center; }
.foot-sup .sup-follow { grid-column: 1 / -1; justify-self: start; }
.site-footer .btn-green { border-color: #FEF1DF; box-shadow: 4px 4px 0 #F2C0AB; }
.site-footer .btn-primary { background: #F2C0AB; color: #56000E; border-color: #FEF1DF; box-shadow: 4px 4px 0 #FEF1DF; }
/* The contact block (a stand-in): the email, the project form, her socials, the dotted note. */
.contact-block { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp2); min-width: 0; }
@media (min-width: 1024px) { .foot-reach .contact-block { align-items: flex-end; text-align: right; } }
.contact-h { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: var(--t1); }
.contact-form { font-weight: 700; display: inline-block; padding: 10px 0; min-height: 44px; }
.contact-note { margin: 0; }
.site-footer .contact-form { color: #FEF1DF; }
.contact-end { padding-top: 0; }
.contact-page { background: #FFFFFF; border: var(--edge); border-radius: var(--radius); box-shadow: var(--hard-sm); padding: var(--sp4); max-width: 860px; }
.contact-page .mail, .contact-page .contact-form { color: #56000E; }
.contact-page .soc { --soc-bg: #56000E; --soc-fg: #FEF1DF; --soc-line: #56000E; }
/* FAQ, Terms and Links: one row of links. */
.foot-pages ul { list-style: none; margin: 0; padding: var(--sp3) 0 0; display: flex; flex-wrap: wrap; gap: var(--sp2) var(--sp5); border-top: 2px dashed #F2C0AB; }
.foot-pages a { color: #FEF1DF; font-weight: 700; display: inline-block; padding: 10px 0; min-height: 44px; }
/* The feed slot: the tiles (ul.ig-grid's look), or the one Instagram link. */
.feed-fallback { margin: 0; }
.feed-ig { display: inline-flex; align-items: center; gap: var(--sp2); }
.feed-ig-ico { display: inline-grid; place-items: center; } .feed-ig-ico svg { width: 24px; height: 24px; fill: currentColor; }
.lk-feed { margin-top: var(--sp5); display: flex; flex-direction: column; align-items: center; }
.lk-feed .feed-grid { width: 100%; }
/* The Worlds index: Home's world cards as a full page. */
.worlds-head { background: #F2C0AB; border-bottom: var(--edge); }
.worlds-head .eyebrow { color: #56000E; }
.world-card .world-cast { display: block; font-weight: 600; margin-top: var(--sp1); }
.world-art-none { display: grid; place-items: center; aspect-ratio: 4 / 3; padding: var(--sp3); text-align: center; }
/* A world page: a cast card with no picture yet, and Rylon's coming-soon block. */
.cast-card-noart .cast-name { margin-top: 0; }
.coming-soon { border-top: var(--edge); }
/* The FAQ page. */
.faq-page .faq-cta { margin-top: var(--sp5); }
/* A world page's name: a three-word name ("Race Against Tempium", "Rylon the Leopard") is held on one line by the
   every-line rule, so below 600 px it scales with the screen instead of running past the card (20.8 px at 320 px). */
@media (max-width: 599px) { .world-hero-text .display { font-size: min(var(--t5), 6.5vw); } }
/* At 320 px a world blurb's longest word ("anthropomorphic", Rylon's draft) had a line to itself at 19 px inside the
   card's 32 px padding; 24/16 px padding and 17 px text give it a partner (the every-line rule; never under 16 px). */
@media (max-width: 359px) { .world-hero-text { padding: var(--sp4) var(--sp3); } .world-hero-text .lead { font-size: 17px; } }
