/* Dojo 12 — frame (review 2026-09-24 art pass). Loaded after app.css and kit.css.
   The title bar on every screen, the game's face on the first screens, the calm rows of
   Settings and For Dad, the first card before round 1, How it works, and What Dad sees.
   Colours are the paper's tokens only, so every paper redraws it; every mask property
   is written twice, -webkit- and plain, for iOS Safari. js/game/frame.js builds it. */

/* ---- screen titles on a dry-brush bar (art/kit/out/brush/README.md). The element is
   the bar: ink through the bar's mask, the title in paper colour on its solid core.
   Sizes are in em of the title's font (22 px: a 44 px bar), so a smaller title gets a
   smaller bar. frame.js picks s, m, l or 2 and sets the width; without it, the m bar. ---- */
.titlebar {
  box-sizing: border-box; display: flex; align-items: center; flex: none;
  width: 12.0em; max-width: 100%; height: 2.0em;
  padding: 0.3em 2.8em 0.469em 0.64em;
  font: 600 22px/1.25 "Shippori Mincho", "Hiragino Mincho ProN", "Yu Mincho", serif;
  color: var(--onInk); background-color: var(--ink);
  white-space: nowrap; overflow: hidden;
  clip-path: none;                      /* app.css's cut-tape polygon */
  -webkit-mask-image: url(../img/titlebar-m.webp);
  -webkit-mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-image: url(../img/titlebar-m.webp);
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
}
.titlebar.bar-s { padding-left: 0.64em; padding-right: 1.818em;
  -webkit-mask-image: url(../img/titlebar-s.webp); mask-image: url(../img/titlebar-s.webp); }
.titlebar.bar-l { padding-left: 0.708em; padding-right: 5.004em;
  -webkit-mask-image: url(../img/titlebar-l.webp); mask-image: url(../img/titlebar-l.webp); }
.titlebar.bar-2 { height: auto; min-height: 3.64em; padding: 0.487em 3.918em 0.65em 0.919em;
  white-space: normal; text-wrap: balance;
  -webkit-mask-image: url(../img/titlebar-2.webp); mask-image: url(../img/titlebar-2.webp); }

/* ---- the game's face: the icon's ensō at full weight with the "12" seal where the icon
   has it (brush kit spec.json, enso-mark.webp.iconSeal: centre 1.031, 0.832 of the mark's
   side, the stone 0.218 of it, so the seal's box is 0.2835; turned -4deg). The seal lies
   outside the ring, so the pair is centred, not the ring: 10 % to the left. ---- */
.fr-face { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.fr-mark { --mark: 168px; position: relative; flex: none; width: var(--mark); height: var(--mark);
  left: calc(var(--mark) * -0.1); }
.fr-mark > i { position: absolute; display: block; }
.fr-mark > .fr-enso { inset: 0; background-color: var(--ink);
  -webkit-mask-image: url(../img/enso-mark.webp); mask-image: url(../img/enso-mark.webp);
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; }
.fr-mark > .hanko-12 { left: 88.93%; top: 69.02%; width: 28.35%; height: 28.35%; transform: rotate(-4deg); }
/* The name, said slowly. */
.fr-name { font: 600 30px/1.2 "Shippori Mincho", "Hiragino Mincho ProN", "Yu Mincho", serif; color: var(--ink); }

/* The ensō is brushed in, head to dry tail, as the icon's was painted; then the seal is
   stamped (ART.md's slam, ending where the icon's seal rests). Reduced motion keeps the
   seal and drops the draw-in (ART.md Motion). */
@property --fr-draw { syntax: '<angle>'; inherits: false; initial-value: 360deg; }
.fr-mark.draw > .fr-enso {
  -webkit-mask-image: url(../img/enso-mark.webp), conic-gradient(from 320deg, #000 var(--fr-draw), transparent calc(var(--fr-draw) + 8deg));
  mask-image: url(../img/enso-mark.webp), conic-gradient(from 320deg, #000 var(--fr-draw), transparent calc(var(--fr-draw) + 8deg));
  -webkit-mask-composite: source-in; mask-composite: intersect;
  animation: fr-draw 640ms cubic-bezier(.35, .1, .3, 1) 120ms both;
}
@keyframes fr-draw { from { --fr-draw: 0deg; } to { --fr-draw: 360deg; } }
/* Drawn: back to the one mask, or the second layer leaves a hairline at the box's edge. */
.fr-mark.draw > .fr-enso.drawn { animation: none;
  -webkit-mask-image: url(../img/enso-mark.webp); mask-image: url(../img/enso-mark.webp); }
.fr-mark.draw > .hanko-12 { animation: fr-slam 130ms ease-out 800ms both; }
@keyframes fr-slam { 0% { transform: scale(1.6) rotate(-7deg); opacity: 0; }
  60% { transform: scale(0.96) rotate(-4deg); opacity: 1; } 100% { transform: rotate(-4deg); opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .fr-mark.draw > .fr-enso { animation: none; -webkit-mask-image: url(../img/enso-mark.webp); mask-image: url(../img/enso-mark.webp); }
  .fr-mark.draw > .hanko-12 { animation-delay: 0ms; }
}

/* ---- the install screen (iPhone Safari only): the face, the reason, the two taps ---- */
.fr-install { align-items: center; text-align: center; }
.fr-install .fr-mark { --mark: clamp(128px, 21vh, 184px); }
.fr-install-line { max-width: 300px; margin-top: 30px; font-size: 17px; font-weight: 700; line-height: 1.4; text-wrap: balance; }
.fr-steps { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 10px; color: var(--ink); }
.fr-steps .fr-g-share { width: 34px; height: 43px; }
.fr-steps .fr-g-add { width: 40px; height: 40px; }
.fr-steps .fr-g-then { width: 22px; height: 10px; color: var(--ink2); }
.fr-install-how { font-size: 15px; color: var(--ink); }

/* ---- glyphs: strokes in the text's colour ---- */
.fr-glyph { display: block; flex: none; overflow: visible; }
.fr-glyph path { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.fr-g-share path, .fr-g-add path { stroke-width: 3; }
.fr-g-go { width: 8px; height: 13px; }
.fr-g-open { width: 13px; height: 8px; transition: transform 120ms ease; }
.fr-g-then { width: 20px; height: 9px; }

/* ---- the name screen: the face, then the question, the field and Start. The face
   sits high, so the field and Start stay above the keyboard when it opens. ---- */
.fr-first .fr-mark { --mark: clamp(108px, 18vh, 160px); }
.fr-first > .fr-lead { flex: 0 0 clamp(4px, 4vh, 40px); }
.fr-first > .fr-face { margin-bottom: 20px; }
.fr-first > .titlebar.fr-centre { align-self: center; }
.fr-first > .field { text-align: center; }
.fr-first > .link.small { align-self: center; }
.fr-first > .grow { flex: 1 1 0px; }
/* A short phone (375 x 667): the keyboard takes about 260 of its 667 points, so the
   face gives up height and Start stays above the keys. */
@media (max-height: 700px) {
  .fr-first .fr-mark { --mark: 96px; }
  .fr-first > .fr-lead { flex-basis: 4px; }
  .fr-first > .fr-face { gap: 8px; margin-bottom: 12px; }
}
/* more than one player: each name in the face names are set in */
.fr-names { align-self: stretch; margin-top: 8px; }
.fr-names .fr-label { font: 600 22px/1.25 "Shippori Mincho", "Hiragino Mincho ProN", "Yu Mincho", serif; }
/* bringing a saved game back: the file link sits under the button, not across the page */
.restorebox > .link { align-self: flex-start; }

/* ---- the one screen before round 1: the title, the card the round will deal and the
   words under it as one group, and Start. ---- */
.fr-demo { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.fr-demo .card { --cs: clamp(150px, 27vh, 232px); flex: none; width: var(--cs); height: var(--cs); }
.fr-intro > .grow { flex: 1 1 0px; }
.fr-intro > .fr-intro-after { flex-grow: 1.4; }
.fr-intro-words { margin-top: 14px; line-height: 1.5; }

/* ---- a calm list of paper rows (Settings, For Dad): ruled like a table in a printed
   book, ink above and below, hairlines between; no box and no shadow on any row. ---- */
.fr-list { display: flex; flex-direction: column; border-top: 1.5px solid var(--ink); border-bottom: 1.5px solid var(--ink); }
.fr-list > :not(:first-child) { border-top: 1px solid var(--rule); }
.fr-row {
  position: relative; display: flex; flex-wrap: wrap; align-items: center; column-gap: 12px; row-gap: 3px;
  width: 100%; min-height: 54px; margin: 0; padding: 14px 4px;
  background: transparent; color: var(--ink); border: 0; border-radius: 0; box-shadow: none;
  font-size: 17px; font-weight: 700; line-height: 1.3; text-align: left;
}
.fr-row:active { background-color: var(--paper2); }
.fr-row:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.fr-row:disabled { cursor: default; }
.fr-row:disabled .fr-label, .fr-row:disabled .fr-end { color: var(--ink2); }
.fr-label { flex: 1 1 0px; min-width: 0; }
.fr-value { flex: none; font-size: 15px; font-weight: 500; color: var(--ink2); }
.fr-end { flex: none; display: flex; align-items: center; justify-content: flex-end; min-width: 13px; color: var(--ink2); }
.fr-end .fr-g-share { width: 15px; height: 19px; }
.fr-end .fr-g-share path { stroke-width: 3.6; }
.fr-note { flex: 0 0 100%; padding-right: 16px; font-size: 13px; font-weight: 500; line-height: 1.45; color: var(--ink2); }
.fr-row[aria-expanded="true"] .fr-g-open { transform: rotate(180deg); }
/* A row that opens under itself: what it opens sits in its slot. */
.fr-item { display: flex; flex-direction: column; }
.fr-slot:empty { display: none; }
.fr-slot { padding: 0 4px 16px; }
/* The quiet rows: For Dad behind its hold, and Start over, which is never red. */
.fr-row.fr-quiet .fr-label { color: var(--ink2); font-weight: 500; }
.fr-solo { border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
/* The two-second hold: an ink line fills along the foot of the row. */
.fr-hold { overflow: hidden; touch-action: none; }
.fr-hold > .fill { position: absolute; left: 0; bottom: 0; width: 0; height: 2px; background: var(--ink); }

/* On and Off. On is the solid red block, "this one, now"; Off is an empty ink outline.
   Both say the word. */
.fr-stamp {
  flex: none; box-sizing: border-box; min-width: 50px; padding: 5px 10px 6px;
  border: 1.5px solid var(--ink); border-radius: 4px; background: transparent; color: var(--ink);
  font-size: 13px; font-weight: 900; line-height: 1.15; text-align: center;
}
.fr-stamp.on { background: var(--shu); border-color: var(--shu); color: var(--onInk); }

/* ---- How it works: five short panels, a picture beside the words of each ---- */
.fr-howto { display: flex; flex-direction: column; }
.fr-panel { display: flow-root; padding: 18px 0 20px; border-top: 1px solid var(--rule); }
.fr-panel:first-child { border-top: 0; padding-top: 4px; }
.fr-panel h3 { margin: 0 0 5px; font-size: 17px; font-weight: 700; line-height: 1.3; }
.fr-panel p { margin: 0; font-size: 15px; line-height: 1.5; }
.fr-pic { float: right; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  margin: 3px 0 8px 16px; }
/* the card, at 116 px */
.fr-pic-card .card { width: 116px; height: 116px; max-width: none; --cs: 116px; gap: 0; }
.fr-pic-card .question { font-size: 21px; letter-spacing: -0.5px; }
.fr-pic-card .answer { font-size: 15px; }
.fr-pic-card .cardtime { min-height: 0; margin-top: 2px; font-size: 10px; line-height: 1.2; }
/* the brush timer, still (brush kit README, "The timer"): the whole stroke faint, and
   in ink from its head to the cut. The cut sits 12deg into the stroke's gap at
   --left 0 and 348deg round at --left 1, soft over 2.5deg either side. */
.fr-timer { position: absolute; inset: 7%; pointer-events: none; }
.fr-timer > i { position: absolute; inset: 0; display: block;
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center; }
.fr-timer > .trail { background-color: var(--ink2); opacity: 0.22; }
.fr-timer > .left { background-color: var(--ink);
  --cut: calc(12deg + 336deg * var(--left, 1));
  --cutmask: conic-gradient(from 313.5deg, #000 calc(var(--cut) - 2.5deg), transparent calc(var(--cut) + 2.5deg));
  -webkit-mask-composite: source-in; mask-composite: intersect; }
/* one pair of rules per timer in the Shop: the url is written out, never kept in a custom property */
.fr-timer > .trail { -webkit-mask-image: url(../img/enso-brush.webp); mask-image: url(../img/enso-brush.webp); }
.fr-timer > .left  { -webkit-mask-image: url(../img/enso-brush.webp), var(--cutmask); mask-image: url(../img/enso-brush.webp), var(--cutmask); }
[data-ring="thin"] .fr-timer > .trail { -webkit-mask-image: url(../img/enso-pen.webp); mask-image: url(../img/enso-pen.webp); }
[data-ring="thin"] .fr-timer > .left  { -webkit-mask-image: url(../img/enso-pen.webp), var(--cutmask); mask-image: url(../img/enso-pen.webp), var(--cutmask); }
[data-ring="double"] .fr-timer > .trail { -webkit-mask-image: url(../img/enso-double.webp); mask-image: url(../img/enso-double.webp); }
[data-ring="double"] .fr-timer > .left  { -webkit-mask-image: url(../img/enso-double.webp), var(--cutmask); mask-image: url(../img/enso-double.webp), var(--cutmask); }
[data-ring="dotted"] .fr-timer > .trail { -webkit-mask-image: url(../img/enso-dotted.webp); mask-image: url(../img/enso-dotted.webp); }
[data-ring="dotted"] .fr-timer > .left  { -webkit-mask-image: url(../img/enso-dotted.webp), var(--cutmask); mask-image: url(../img/enso-dotted.webp), var(--cutmask); }
[data-ring="gold"] .fr-timer > .left { background-color: var(--kin); }
/* the ticks, on the same box as the mask; drawn a little heavier than the round's,
   so they still read on a card a third of its size */
.fr-ticks { position: absolute; inset: 7%; width: 86%; height: 86%; pointer-events: none; overflow: visible; }
.fr-ticks line { stroke-linecap: butt; }
.fr-ticks .gold { stroke: var(--kin); stroke-width: 3; }
.fr-ticks .best { stroke: var(--ink); stroke-width: 2; }
[data-ring="gold"] .fr-ticks .gold { stroke: var(--ink); }
/* the seal: halfway, then sealed, in the card corner's own stack */
.fr-pic-seal { flex-direction: row; gap: 9px; }
.fr-pic-seal .fr-g-then { color: var(--ink2); }
.fr-stack { position: relative; display: block; flex: none; width: 50px; height: 50px; transform: rotate(-3deg); }
.fr-stack > i { position: absolute; inset: 0; width: auto; height: auto; }
/* the belt */
.fr-pic-belt { width: 150px; }
.fr-pic-belt .belt { width: 150px; }
/* the streak's three steps */
.fr-pic-streak { display: grid; grid-template-columns: auto auto; align-items: center; column-gap: 7px; row-gap: 8px; }
.fr-pic-streak .streak { display: contents; }
.fr-pic-streak .label { justify-self: end; }
.fr-pic-streak .mult { justify-self: start; }
/* points, a coin, a level */
.fr-pic-coins { align-items: flex-start; gap: 8px; }
.fr-pic-coins .scorebox { gap: 5px; }
.fr-coinrow { display: flex; align-items: center; gap: 14px; }
.fr-coinrow .coin.big { width: 30px; height: 30px; vertical-align: 0; }
.fr-pic-coins .hanko-level { width: 42px; height: 42px; }
.fr-pic-coins .hanko-level > b { font-size: 25px; }

/* ---- What Dad sees: a report on paper, plain and adult. The name and level over an
   ink rule, one ruled section a subject, the child's tied belt as Home draws it. A
   check that fails is set heavier in ink, never red. ---- */
.fr-dash { width: 100%; max-width: 560px; margin: 0 auto; gap: 0; }
.fr-dash-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 2px 0 12px; border-bottom: 1.5px solid var(--ink); }
.fr-dash-level { flex: none; font-size: 17px; font-weight: 700; }
.fr-sec { display: flex; flex-direction: column; gap: 7px; padding: 14px 0 16px; }
.fr-sec + .fr-sec { border-top: 1px solid var(--rule); }
.fr-sec > .label { margin-bottom: 1px; }
.fr-flag { font-weight: 700; }
.fr-dash-belt { width: min(100%, 250px); margin: 2px 0 4px; }
.fr-dash > .btn { margin-top: 12px; }

/* Numerals are never Mincho (ART.md): digits inside a Mincho title or the game's name are
   set in Zen Kaku Gothic, a shade smaller so they sit on the Mincho's line. */
.tnum { font-family: "Zen Kaku Gothic New", "Hiragino Sans", system-ui, sans-serif; font-weight: 700;
  font-size: 0.94em; font-variant-numeric: tabular-nums; letter-spacing: 0; }
