/* ARSENE — characters.css
 * Layer rules, states, hues, misprint, idle loops, hover reactions, rose styles.
 * No literal colours: everything reads tokens from css/tokens.css. */

/* ---------- mounts ---------- */
.char-mount { display: block; position: relative; }
.rose-mount { display: inline-block; vertical-align: middle; line-height: 0; }
.char-mount > svg, .rose-mount > svg { display: block; width: 100%; height: 100%; }

/* ---------- the character root ---------- */
.char {
  display: block;
  overflow: visible;
  --mis-x: 6px;
  --mis-y: -4px;
  --c-hue: var(--hue, var(--rose));
}
.char--sable   { --c-hue: var(--hue-nocturne); }
.char--kestrel { --c-hue: var(--hue-kestrel); }
.char--deniz   { --c-hue: var(--hue-saltwater); }
.char--king    { --c-hue: var(--hue-gilded); }
.char--pip     { --c-hue: var(--hue-paper); }

/* ---------- layers ---------- */
/* ink: the paper cut-out. Fills live on the group so a <use> of the mass path in .rim inherits the rim's paint instead. */
.char .ink {
  fill: var(--char-ink);
  stroke: var(--paper);
  stroke-width: 1;
  stroke-opacity: .85;
  stroke-linejoin: round;
}
.char .ink :is(path, rect, circle, ellipse, polygon, polyline, line) { vector-effect: non-scaling-stroke; }

/* tone: halftone dots */
.char .ht-dot { fill: var(--c-hue); }
.char .ht-dot--ink { fill: var(--char-ink); }
.char .tone { pointer-events: none; }

/* rim: grazing light from the upper-left (the stroke is clipped to the mass, so 1.5px survives) */
.char .rim { fill: none; stroke-width: 3; }
.char .rim use { vector-effect: non-scaling-stroke; }
.char .rim-stop { stop-color: var(--paper); }
.char .rim-stop--a { stop-opacity: .55; }
.char .rim-stop--b { stop-opacity: 0; }

/* accent: the hue */
.char .accent { fill: var(--c-hue); stroke: var(--c-hue); stroke-width: 0; stroke-linecap: round; }
.char .accent--print {
  mix-blend-mode: screen;
  opacity: .9;
  transform: translate(var(--mis-x), var(--mis-y));
  transition: transform .6s cubic-bezier(.76,0,.24,1);
}
/* registered: set by a class when the figure is centred/attended (gallery, index), never per frame */
.char.is-registered { --mis-x: 0px; --mis-y: 0px; }
/* the gallery adds .is-live to the centred spread's character only (brief 8.4) */
.char.is-live .accent--print { will-change: transform; }
/* lite mode: registration becomes a 300ms class toggle instead of a scrub (brief 8.4) */
html[data-lite] .char .accent--print { transition: transform .3s cubic-bezier(.76,0,.24,1); }
/* only the ink takes the pointer, so hover reactions resolve on the paper cut-out itself */
.char :is(.tone, .rim, .accent, .glow, .detail, .plan) { pointer-events: none; }

/* detail: ivory features */
.char .detail { fill: var(--paper); stroke: var(--paper); stroke-width: 0; stroke-linecap: round; stroke-linejoin: round; }
.char .detail [fill="none"], .char .detail line { fill: none; }
.char .detail .seam { stroke-width: 1; stroke-opacity: .45; vector-effect: non-scaling-stroke; }

/* plan: Blueprint. Hidden by default; the dossier lens, .is-plan and proof mode reveal it. */
.char .plan { display: none; fill: none; stroke: var(--paper); stroke-width: 1; }
.char .plan * { vector-effect: non-scaling-stroke; }
.char .plan-guide { opacity: .4; }
.char .plan-dim { opacity: .7; }
.char .plan-label {
  fill: var(--paper);
  stroke: none;
  font-family: "JetBrains Mono", Menlo, monospace;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.char .plan-void { fill: var(--char-ink); stroke: var(--paper); }
.char.is-plan .plan { display: block; }

/* inside the stencil windows (hero) the cut-outs print one step lighter, with a full-strength paper edge and
   crisper seams, so the letters never read as empty black */
.drift__char .char { --char-ink: var(--char-ink-lit); }
.drift__char .char .ink { stroke-opacity: 1; stroke-width: 1.5; }
.drift__char .char .detail .seam { stroke-opacity: .7; }
.drift__char .char .rim-stop--a { stop-opacity: .8; }

/* ---------- states ---------- */
/* (silhouette rules sit at the end of the file with a type selector so they outrank every per-character fill) */

/* proof mode: no misprint, no halftone, the plan over the duotone at .7 */
html[data-proof]:not([data-proof="false"]) .char .accent--print,
html[data-proof]:not([data-proof="false"]) .char .tone,
html[data-proof]:not([data-proof="false"]) .char .glow { display: none; }
html[data-proof]:not([data-proof="false"]) .char:not(.state-silhouette) .plan { display: block; opacity: .7; }
html[data-proof]:not([data-proof="false"]) .char .accent--print { transform: none; }
html[data-proof]:not([data-proof="false"]) .char .plan-void { opacity: 1; }

/* ---------- per-character ---------- */
/* Madame Sable */
.char--sable .ink .card { fill: var(--paper); stroke: none; }   /* the calling card: the one ivory fill in the ink layer */
.char--sable .card-a {
  fill: var(--c-hue);
  font-family: "Instrument Serif", Georgia, serif;
  font-style: italic;
  font-size: 18px;
}
.char--sable .detail .monocle { stroke-width: 1.5; transform-box: fill-box; transform-origin: center; transition: transform .18s cubic-bezier(.76,0,.24,1); }
.char--sable .detail .chain { stroke-width: 1; transition: transform .18s cubic-bezier(.76,0,.24,1); }
.char--sable .rock { transform-box: view-box; transform-origin: 236px 330px; }

/* Unit K-9 */
.char--kestrel .chev { stroke-width: 2; }
.char--kestrel .glow { fill: var(--c-hue); opacity: .6; pointer-events: none; transition: opacity .18s cubic-bezier(.76,0,.24,1); }
.char--kestrel .gimbal { stroke-width: 3; }
.char--kestrel .tip { transition: transform .18s cubic-bezier(.76,0,.24,1); }
.char--kestrel .detail .unit { fill: var(--paper); stroke: none; fill-opacity: .85; font-family: "JetBrains Mono", Menlo, monospace; font-size: 13px; font-weight: 500; letter-spacing: .22em; }

/* Deniz */
.char--deniz .detail .blade { fill: var(--char-ink); stroke-width: 1; stroke-opacity: .85; vector-effect: non-scaling-stroke; }
.char--deniz .waves { stroke-width: 2; }
.char--deniz .detail .halo { stroke-width: 1.5; transition: stroke-dashoffset .6s cubic-bezier(.76,0,.24,1); }
.char--deniz .detail .hair { stroke-width: 2; }
.char--deniz .detail .gull { stroke-width: 1.5; }

/* The Hollow King */
.char--king .chain { stroke-width: 2.5; }
.char--king .cracks { stroke-width: 2; }
.char--king .crack { stroke-dasharray: 100 100; stroke-dashoffset: 30; transition: stroke-dashoffset .4s cubic-bezier(.76,0,.24,1); }
.char--king .slit { transition: opacity .4s; }
.char--king .pleats { stroke-width: 1; stroke-opacity: .5; }
.char--king .tri { transform-box: view-box; transform-origin: 268px 72px; }

/* Pip: the only figure whose ink is coloured paper; folds are 1px ink lines, the contour is lit by the rim */
.char--pip .ink { fill: var(--hue-paper); stroke: var(--char-ink); stroke-opacity: .7; }
.char--pip .ink .pl { fill: var(--peach-light); }
.char--pip .ink .pm, .char--pip .ink .inner { fill: var(--peach-mid); }
.char--pip .ink .pp, .char--pip .ink .ear, .char--pip .ink .tip { fill: var(--hue-paper); }
.char--pip .ink .tail { fill: var(--paper); }
.char--pip .detail .chest, .char--pip .detail .snout { fill: var(--paper); stroke: var(--char-ink); stroke-width: 1; stroke-opacity: .7; vector-effect: non-scaling-stroke; }
.char--pip .detail .dot { fill: var(--char-ink); stroke: none; }
.char--pip .accent { fill: var(--peach-mid); stroke: none; }
.char--pip .detail .string { stroke-width: 1; }
.char--pip .moon { transform-box: view-box; transform-origin: 96px 440px; }
.char--pip .ear, .char--pip .inner { transform-box: view-box; }
.char--pip .ear--l, .char--pip .inner--l { transform-origin: 121px 166px; --twitch: -8deg; }
.char--pip .ear--r, .char--pip .inner--r { transform-origin: 179px 166px; --twitch: 8deg; }

/* ---------- idle loops (one per character, only while awake, never under reduced motion) ---------- */
.char--sable.is-awake .rock { animation: sable-rock 6s ease-in-out infinite; }
@keyframes sable-rock { 0%, 100% { transform: rotate(-3deg); } 50% { transform: rotate(3deg); } }

.char--kestrel.is-awake .chev { animation: kestrel-chev 1.2s ease-in-out infinite; }
.char--kestrel.is-awake .chev--2 { animation-delay: .3s; }
.char--kestrel.is-awake .chev--3 { animation-delay: .6s; }
@keyframes kestrel-chev { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }

.char--deniz.is-awake .waves { animation: deniz-waves 5s ease-in-out infinite; }
@keyframes deniz-waves { 0%, 100% { transform: translateX(-6px); } 50% { transform: translateX(6px); } }

.char--king.is-awake .tri { animation: king-tri 12s linear infinite; }
@keyframes king-tri { to { transform: rotate(360deg); } }

.char--pip.is-awake .moon { animation: pip-moon 4s ease-in-out infinite; }
@keyframes pip-moon { 0%, 100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg); } }

/* ---------- hover micro-reactions (pointer devices) ---------- */
@media (hover: hover) {
  .char--sable:hover .detail .monocle { transform: scale(1.15); }
  .char--sable:hover .detail .chain { transform: translateY(2px); }
  .char--kestrel:hover .glow { opacity: 1; }
  .char--kestrel:hover .tip--l { transform: translate(-2.2px, -2.1px); }
  .char--kestrel:hover .tip--r { transform: translate(2.2px, -2.1px); }
  .char--deniz:hover .detail .halo { stroke-dashoffset: 10; }
  /* the void: rest on the King for 1.5s and the cracks grow a 40px tail, the slits dim; both revert on leave */
  .char--king:hover .crack { stroke-dashoffset: 0; transition: stroke-dashoffset .8s cubic-bezier(.76,0,.24,1) 1.5s; }
  .char--king:hover .slit { opacity: .4; transition: opacity .8s 1.5s; }
}
/* the same void on demand (the dossier lens / a page timer adds .is-void after 1.5s of rest on the mask) */
.char--king.is-void .crack { stroke-dashoffset: 0; transition: stroke-dashoffset .8s cubic-bezier(.76,0,.24,1); }
.char--king.is-void .slit { opacity: .4; transition: opacity .8s; }
@media (hover: hover) {
  .char--pip:hover .ear, .char--pip:hover .inner { animation: pip-twitch .24s ease-in-out; }
}
/* Pip's ears also twitch on demand (Correspondence field focus): add .is-twitch, remove it after 240ms */
.char--pip.is-twitch .ear, .char--pip.is-twitch .inner { animation: pip-twitch .24s ease-in-out; }
@keyframes pip-twitch { 50% { transform: rotate(var(--twitch, -8deg)); } }

/* ---------- the rose ---------- */
.rose { display: block; overflow: visible; }
.rose .petal-stop { stop-color: var(--rose); }
.rose .petal-stop--lit { stop-color: var(--rose-petal-0, var(--rose)); }
.rose .petal-stop--mid { stop-color: var(--rose-petal-1, var(--rose-deep)); }
.rose .petal-stop--dark { stop-color: var(--rose-dark); }
.rose .petal-fill { stroke: none; }
.rose .petal-outline { fill: none; stroke: var(--rose-stroke, var(--rose-dark)); stroke-width: 2; stroke-opacity: .8; stroke-linejoin: round; stroke-linecap: round; }
.rose .rose-glow { fill: var(--rose-glow); opacity: .35; }
.rose .rose-shade { opacity: .55; fill: var(--rose-dark); }
.rose .rose-shade-flood { flood-color: var(--rose-dark); flood-opacity: 1; }
.rose .rose-spiral { stroke: var(--rose-stroke, var(--rose-dark)); stroke-width: 1.2; stroke-opacity: .85; stroke-linecap: round; }
.rose .rose-body { transform-box: view-box; transform-origin: 100px 104px; }
.rose .petal-open { transform-box: view-box; transform-origin: 0 0; transition: transform .18s cubic-bezier(.76,0,.24,1); }
.rose.is-breathing .rose-body { animation: rose-breathe 6s ease-in-out infinite; }
@keyframes rose-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.015); } }
@media (hover: hover) {
  /* hero rose hover: the outer three petals open 4 degrees about the bud (brief 6.2) */
  .rose:hover .petal--outer .petal-open--a { transform: rotate(-4deg); }
  .rose:hover .petal--outer .petal-open--b { transform: rotate(4deg); }
}
html[data-proof]:not([data-proof="false"]) .rose .rose-glow,
html[data-proof]:not([data-proof="false"]) .rose .rose-shade { display: none; }

.rose-glyph { display: block; overflow: visible; }
.rose-seal { display: block; overflow: visible; }
.rose-seal .seal-text {
  font-family: "Instrument Serif", Georgia, serif;
  font-style: italic;
  font-size: 15px;
}

/* ---------- silhouette state (last: must outrank every per-character fill rule) ---------- */
svg.char.state-silhouette .ink, svg.char.state-silhouette .ink * { fill: currentColor; stroke: none; }
svg.char.state-silhouette .tone, svg.char.state-silhouette .rim, svg.char.state-silhouette .accent,
svg.char.state-silhouette .detail, svg.char.state-silhouette .glow { display: none; }

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .char .rock, .char .chev, .char .waves, .char .tri, .char .moon, .char .ear, .char .inner,
  .rose .rose-body, .rose .petal-open { animation: none !important; transition: none !important; }
  .char .accent--print { transform: none; }
}
