/* Novia Chao — homepage v2. Dark field, white cards, animated double-diamond band. */

/* Typography. Whyte Inktrap ships as ten static cuts, declared here as one family so
   font-weight selects between them; a browser only downloads the cuts a page actually
   uses, so the page still fetches Medium alone. Book sits at 350 and there is no 600.
   Diatype is variable across 200-1000, so one file covers both the Regular body copy
   and the Medium navigation. */
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Thin.woff2") format("woff2");font-weight:100;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Extralight.woff2") format("woff2");font-weight:200;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Light.woff2") format("woff2");font-weight:300;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Book.woff2") format("woff2");font-weight:350;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Regular.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Medium.woff2") format("woff2");font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Bold.woff2") format("woff2");font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Heavy.woff2") format("woff2");font-weight:800;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Black.woff2") format("woff2");font-weight:900;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Whyte Inktrap";src:url("fonts/ABCWhyteInktrapArabicTrial-Super.woff2") format("woff2");font-weight:1000;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Diatype";src:url("fonts/ABCDiatypeArabicVariableTrial.woff2") format("woff2");font-weight:200 1000;font-style:normal;font-display:swap}
@font-face{font-family:"ABC Favorit";src:url("fonts/ABCFavoritArabicVariableTrial.ttf") format("truetype");font-weight:300 1000;font-style:normal;font-display:swap}

:root{
  /* --ground is the page behind everything; --ink is text. They used to be one token,
     which only worked while the page and the type were the same colour. Anything that
     punches a hole in the band — a node ring's fill, a label's halo — has to track the
     ground, not the ink. */
  --ground:#EFEEEC;
  --ink:#1D1A0C;
  --text:#4A4536;
  --surface:#fff;
  /* White on a bone ground is a 2% step, so the surfaces need an edge to read as surfaces
     rather than as faintly brighter page. */
  --hairline:#0000001a;
  --surface-sunk:#f8f8f8;
  --surface-active:#ededed;
  --line:#333DBE;
  /* The one warm colour on the site, and it exists for exactly one thing: the eye of the flowers
     on the opening screen. The screen is blue and bone, which is a soft version of the warm-on-
     cool contrast the reference gets its punch from; amber is the version that punches. It is
     named rather than written into boot.js so it can be changed or removed in one place, and so
     the next person can see there is deliberately only one of these. */
  --bloom:#E9A13B;
  /* The grid rules. Ink at 15% rather than a neutral grey, so they sit in the same warm
     family as the type instead of introducing a third temperature. */
  --rule:#1d1a0c40;
  /* The subdivisions. Present enough to measure against, quiet enough that the vertices and
     apexes still read as the structure and these as the ticks between them. */
  --rule-minor:#1d1a0c14;
  --edge:16px;
  --radius:4px;
}

*{box-sizing:border-box}
/* The hero is a viewport, not a page. height:100% asked the parent chain how tall to be, which
   is a question with no answer when the document is embedded in a frame that has not been
   measured yet — the page then has zero height and renders nothing. Asking the viewport directly
   cannot fail that way; the percentage stays first for anything without dvh. */
html{height:100%}
body{margin:0;min-height:100%;min-height:100dvh;background:var(--ground);color:var(--text);font-synthesis:none;-webkit-font-smoothing:antialiased;overflow:hidden}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer;-webkit-tap-highlight-color:transparent}
:focus-visible{outline:2px solid var(--line);outline-offset:3px;border-radius:2px}
/* An author display rule beats the hidden attribute's UA style, and the contact menu sets
   display:flex — so without this it was never actually hidden. */
[hidden]{display:none!important}

/* The grid the band casts: a rule at every vertex and every apex, full height, behind
   everything. Drawn once per build from the same geometry the band is built from, which is
   why it is a grid and not a decoration that happens to line up. */
.grid{position:fixed;inset:0;z-index:0;pointer-events:none}
.grid svg{display:block;width:100%;height:100%}
/* non-scaling-stroke because the svg is stretched to the viewport: without it the rules
   would be scaled by the viewBox and come out at some fraction of a pixel. */
.dd-rule{stroke:var(--rule);stroke-width:1;stroke-dasharray:4 7;vector-effect:non-scaling-stroke}
.dd-rule.is-minor{stroke:var(--rule-minor);stroke-dasharray:2 9}

/* Diamond field */
.field{position:fixed;inset:0;z-index:1;pointer-events:none}
.field svg{display:block;width:100%;height:100%;overflow:visible}
.field canvas{display:block;width:100%;height:100%}
/* non-scaling-stroke is what makes the turn work: as a shape flattens towards the
   spindle its stroke stays 4px, so it resolves into the line instead of thinning away.
   Geometry and transforms are driven per frame from home-v2.js. */
.dd-line{fill:none;stroke:var(--line);stroke-width:var(--stroke,2);stroke-linejoin:round;vector-effect:non-scaling-stroke}
.dd-spindle{stroke:var(--line);stroke-width:var(--stroke,2);vector-effect:non-scaling-stroke}
/* The vertices the strands share. Filled with the page colour so the band is cut at each
   junction rather than merely dotted — a point you could stop at, not a bead on a wire. */
.dd-node{fill:var(--ground);stroke:var(--line);stroke-width:var(--stroke,2);vector-effect:non-scaling-stroke}
/* Names whichever act the pointer is performing on the diamond it is inside. */
.dd-label{fill:var(--line);opacity:0;transition:opacity .12s linear;paint-order:stroke;stroke:var(--ground);stroke-width:7;stroke-linejoin:round}

/* Top navigation */
.topbar{position:fixed;top:var(--edge);right:var(--edge);z-index:2}
/* Natural width, links close together: four short words read as one control, not a spread. */
.nav{display:flex;align-items:center;justify-content:flex-start;gap:2px;width:auto;padding:4px 12px 4px 4px;background:var(--surface);border-radius:var(--radius);border:1px solid var(--hairline)}
/* The way back, and the only place most pages say whose site this is. It sits on the left on its
   own rather than inside the navigation: the navigation is a list of places to go, and home is not
   one more of those — it is where you already came from. Keeping it apart is what makes it read as
   a way out rather than as a fifth section. */
.brand{position:fixed;top:var(--edge);left:var(--edge);z-index:3;display:flex;align-items:center;gap:7px;padding:5px 11px 5px 9px;background:var(--surface);border:1px solid var(--hairline);border-radius:var(--radius);color:var(--ink);white-space:nowrap;transition:color .18s,border-color .18s}
a.brand:hover,a.brand:focus-visible{color:var(--line);border-color:var(--line)}
/* On the homepage it holds still, and lives inside the card rather than floating above it — that
   page has a surface to put it on and the others do not. */
.brand.is-here{position:static;padding:0;background:none;border:0;cursor:default}
.card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}
/* The mark keeps the band's colour while the name stays ink, so the pair reads as a lockup and the
   square is what the eye lands on. Square and solid rather than the band's drawn diamond: at
   fourteen pixels a 1.5px outline is most of the shape, and what survives at that size is mass,
   not line. */
.brand-mark{width:14px;height:14px;flex-shrink:0;color:var(--line)}
/* Turned on its corner here rather than in the path, so a hover has an angle to turn from. A full
   revolution rather than a quarter: a square is the same square every ninety degrees, so a quarter
   turn is a spin nobody can see happen. transform-box is what makes the origin the square's own
   centre — without it the rotation pivots on the SVG viewport's corner and the mark swings out of
   its own box. */
.brand-mark rect{transform:rotate(45deg);transform-box:fill-box;transform-origin:center;
  transition:transform .7s cubic-bezier(.3,.8,.3,1)}
/* The homepage holds the mark in its card and every other page holds it in the panel, so both get
   the turn. On the panel it is also a link, which is the one place the flourish has a job: it
   answers "is this clickable" before the cursor has stopped moving. */
.brand:hover .brand-mark rect,
.side-home:hover .brand-mark rect,
.side-home:focus-visible .brand-mark rect{transform:rotate(405deg)}
@media(prefers-reduced-motion:reduce){
  .brand-mark rect{transition:none}
  .brand:hover .brand-mark rect,
  .side-home:hover .brand-mark rect,
  .side-home:focus-visible .brand-mark rect{transform:rotate(45deg)}
}

.nav-link,.nav-plus{display:flex;align-items:center;justify-content:center;padding:4px 8px;border-radius:2px;color:var(--text);opacity:.8;white-space:nowrap;transition:background-color .18s,opacity .18s}
.nav-link:hover{opacity:1;background:var(--surface-sunk)}
.nav-link.is-current{background:var(--surface-active);opacity:1}
.nav-plus{padding:0;width:20px;height:20px;margin-left:4px;transition:transform .18s ease,opacity .18s}
.nav-plus svg{width:20px;height:20px}
.nav-plus:hover{opacity:1}
/* The plus turns into a close on open, which is the same glyph a quarter turn on. */
/* A wave, said with the hand: it waves once on hover, from the wrist, and holds still while the
   menu is open. The hand is Phosphor's hand-waving icon (regular), MIT licensed,
   © 2023 Phosphor Icons — https://github.com/phosphor-icons/core */
.nav-plus svg{transform-origin:70% 85%}
.nav-plus:hover svg,.nav-plus:focus-visible svg{animation:wave .7s ease-in-out}
@keyframes wave{0%,100%{transform:rotate(0)}20%{transform:rotate(16deg)}40%{transform:rotate(-8deg)}60%{transform:rotate(14deg)}80%{transform:rotate(-4deg)}}
@media(prefers-reduced-motion:reduce){.nav-plus:hover svg,.nav-plus:focus-visible svg{animation:none}}
.nav-plus[aria-expanded="true"]{opacity:1}

/* Contact menu. Hangs off the topbar rather than the nav so its right edge lines up with
   the nav's, not with the plus. */
.contact-menu{position:absolute;top:calc(100% + 8px);right:0;z-index:3;display:flex;flex-direction:column;min-width:200px;padding:4px;background:var(--surface);border-radius:var(--radius);border:1px solid var(--hairline)}
.contact-link{padding:6px 10px;border-radius:2px;color:var(--text);opacity:.8;white-space:nowrap;transition:background-color .15s,opacity .15s}
.contact-link:hover,.contact-link:focus-visible{opacity:1;background:var(--surface-active)}

/* Intro card */
/* One column at a card's padding, so the name and everything under it share a left edge. The name
   lands 8px from where it sits on the other pages' chip, which the page transition reads as a
   settle rather than a move. Spacing does the hierarchy: the name, a clear jump to the headline,
   then the two lede lines held together as one group under it. */
/* The card runs from the edge inset to the first rule past its own minimum, so its right
   edge is a grid position rather than a number. home-v2.js sets --card-w from the same
   lattice it draws; 502px is the floor it had before, used until a rule is found. */
.card{position:fixed;top:var(--edge);left:var(--edge);z-index:2;display:flex;flex-direction:column;gap:12px;align-items:flex-start;width:min(var(--card-w,502px),calc(100vw - var(--edge) * 2));padding:18px 20px 20px;background:var(--surface);border-radius:var(--radius);border:1px solid var(--hairline)}
/* Place and time, as two tags in the bottom-left corner of the viewport: the card's mirror on the
   diagonal, and the same white-on-bone surface as the navigation and the replay button. */
.locale{position:fixed;left:var(--edge);bottom:var(--edge);z-index:2;display:flex;gap:6px;margin:0}
.locale-tag{padding:5px 9px;background:var(--surface);border:1px solid var(--hairline);border-radius:var(--radius);color:var(--text);white-space:nowrap;font-variant-numeric:tabular-nums}
/* Sizing comes from .t-title and .t-body in the typekit; only the colour is this page's
   business. The 454px measure these carried was exactly the card's content box, so it did
   nothing then and would only have held the text back from the card now that the card is
   the grid's width. No text-wrap:balance — the heading is one line at
   every width the card can be. */
h1{margin:0;color:var(--ink)}
.lede{margin:0}
.card{gap:0}
.card h1{margin-top:18px}
.card .lede{margin-top:10px}
.card .lede + .lede{margin-top:6px}
/* The heading's second sentence starts its own line rather than running on from the first. */
.card h1 .then{display:block}

/* Wordle. The palette is the site's rather than Wordle's green and yellow: on a bone ground
   beside a #333DBE band, green and yellow would be the only other saturated things on the
   page and would win. So a placed letter takes the band's own blue, a letter in the wrong
   place takes an ochre warm enough to sit with the ink, and an absent one goes quiet. */
.wordle-anchor{position:relative;display:inline-block}
/* The trigger has to look like the sentence it is part of, and still be findable. The dashed
   underline is the grid's dash pattern, at the grid's own weight. */
.wordle-trigger{padding:0 3px;margin:0 -3px;border-radius:2px;color:inherit;border-bottom:1px dashed var(--rule);line-height:inherit;transition:background-color .15s,color .15s,border-color .15s}
.wordle-trigger:hover,.wordle-trigger:focus-visible,.wordle-trigger[aria-expanded="true"]{background:#333dbe14;border-bottom-color:var(--line);color:var(--line)}
/* A link out, beside the game's button: the same hover, but a solid rule where the button's is
   dashed, so one reads as a place to go and the other as a thing to open. New tab, like the
   contact links, so the band is never navigated away from. */
.lede-link{padding:0 3px;margin:0 -3px;border-radius:2px;color:inherit;border-bottom:1px solid var(--rule);transition:background-color .15s,color .15s,border-color .15s}
.lede-link:hover,.lede-link:focus-visible{background:#333dbe14;border-bottom-color:var(--line);color:var(--line)}

.wordle{position:absolute;top:calc(100% + 10px);left:0;z-index:4;display:flex;flex-direction:column;gap:10px;width:max-content;max-width:min(320px,calc(100vw - var(--edge) * 4));padding:14px;background:var(--surface);border:1px solid var(--hairline);border-radius:var(--radius);box-shadow:0 12px 32px #1d1a0c14;cursor:default}
.wordle-board{display:flex;flex-direction:column;gap:5px}
/* The tiles turn around their own horizontal axis, so the row they sit in is what has to
   hold the vanishing point. Without it the flip reads as a vertical squash. */
.wordle-row{display:flex;gap:5px;perspective:620px}
.wordle-tile{display:flex;align-items:center;justify-content:center;width:46px;height:46px;border:1px solid var(--hairline);border-radius:2px;color:var(--ink);text-transform:uppercase}
.wordle-tile.is-typed{border-color:#1d1a0c59}
.wordle-tile.is-exact{background:var(--line);border-color:var(--line);color:var(--surface)}
.wordle-tile.is-present{background:#B8873A;border-color:#B8873A;color:var(--surface)}
.wordle-tile.is-absent{background:#1d1a0c1f;border-color:transparent;color:var(--text)}
.wordle-status{margin:0;min-height:15px;color:var(--text)}

.wordle-keys{display:flex;flex-direction:column;gap:4px}
.wordle-keyrow{display:flex;justify-content:center;gap:4px}
.wordle-key{flex:1;min-width:0;padding:7px 0;background:#1d1a0c0f;border-radius:2px;color:var(--ink);text-transform:uppercase;transition:background-color .15s}
.wordle-key.is-wide{flex:1.5}
.wordle-key:hover{background:#1d1a0c1f}
.wordle-key.is-exact{background:var(--line);color:var(--surface)}
.wordle-key.is-present{background:#B8873A;color:var(--surface)}
.wordle-key.is-absent{background:#1d1a0c1f;color:#1d1a0c73}

/* The card is anchored to the top of the viewport, so the board can only ever open downward
   — flipping it upward on a short screen would push it off the top instead. It compacts
   instead, which is what actually buys the room. */
@media(max-height:820px){
  .wordle-tile{width:38px;height:38px}
  .wordle{padding:12px;gap:8px}
  .wordle-key{padding:6px 0}
}

/* Replay control */
.replay{position:fixed;bottom:var(--edge);right:var(--edge);z-index:2;padding:8px 12px;background:#0000000a;border:1px solid #00000022;border-radius:var(--radius);color:var(--ink);opacity:0;transition:opacity .2s,background-color .2s}
body:hover .replay,.replay:focus-visible{opacity:1}
.replay:hover{background:#00000014}
.replay span{margin-left:6px}

@media(max-width:900px){
  :root{--edge:12px}
  .card{width:calc(100vw - var(--edge) * 2)}
  .topbar{top:auto;bottom:var(--edge);right:var(--edge);left:var(--edge)}
  /* The navigation takes the foot of the screen here, so the tags sit just above it. */
  .locale{bottom:calc(var(--edge) * 2 + 40px)}
  .nav{justify-content:space-between;gap:2px}
  /* The bar sits at the bottom on small screens, so the menu opens upward. */
  .contact-menu{top:auto;bottom:calc(100% + 8px)}
  .replay{display:none}
}
@media(max-width:420px){
  .nav-link{padding:6px}
  .brand{padding:5px 9px 5px 8px}
}

/* home-v2.js also reads this query and holds every shape fully open, so the band
   renders as the static composition from the comp. */
@media(prefers-reduced-motion:reduce){
  .replay{display:none}
  *{transition:none!important}
}
