/* ============================================================
   RUMO — shared stylesheet for interior pages (lessons, revisões,
   reference, grammar, histórias). "Papel & Grafite" design system.
   Linked via <link rel="stylesheet" href="[../]shared/style.css">
   ============================================================ */

/* Carlito (SIL OFL 1.1), metric-compatible with Calibri — self-hosted, no Google request */
@font-face{font-family:'Carlito';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/Carlito-Regular.woff2') format('woff2');}
@font-face{font-family:'Carlito';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/Carlito-Bold.woff2') format('woff2');}
@font-face{font-family:'Carlito';font-style:italic;font-weight:400;font-display:swap;src:url('fonts/Carlito-Italic.woff2') format('woff2');}
@font-face{font-family:'Carlito';font-style:italic;font-weight:700;font-display:swap;src:url('fonts/Carlito-BoldItalic.woff2') format('woff2');}

:root{
  --paper:#f6f4ee; --paper-raised:#f1eee3; --ink:#312f2a; --ink-soft:#686254;
  --accent:#3c6a4c; --accent-deep:#2f5540; --clay:#8f5236; --clay-deep:#78432c; --accent-wash:rgba(60,106,76,.10);
  --rule:rgba(49,47,42,.14);
  --good:#3c6a4c; --bad:#a4463a; --bad-wash:#f6e9e6; --good-wash:#eaf1ec;
  /* level ramp, pulled to one chroma so the four read as a family */
  --a2:#7a6434; --b1:#3a6273; --b2:#6d4a63;
  --radius:3px;
  --font-head:Calibri,Carlito,'Segoe UI',system-ui,-apple-system,sans-serif;
  --font-body:Calibri,Carlito,'Segoe UI',system-ui,-apple-system,sans-serif;
  --font-mono:Consolas,'Carlito',ui-monospace,'SFMono-Regular',monospace;

  /* legacy variable names kept as aliases so nothing silently falls back
     to a browser default if a selector was missed below */
  --green:var(--accent); --green-dark:var(--accent-deep); --green-light:var(--accent);
  --yellow:var(--accent-deep); --blue:var(--accent-deep);
  --muted:var(--ink-soft); --bg:var(--paper); --card:var(--paper-raised); --line:var(--rule);
}
html{font-size:17px;}
*{box-sizing:border-box; margin:0; padding:0;}
/* clip, NOT hidden. `overflow-x:hidden` turns the element into a scroll
   container, and that silently kills position:sticky on every descendant —
   which is why the lesson step bar was never really sticky: it scrolled away
   with the page and left a learner on a phone with no navigation on screen at
   all. `clip` cuts exactly the same horizontal overflow (mostly the hidden
   hover-translation tooltips, which hang past the right edge) without creating
   a scroll container, so sticky works and the page still never scrolls
   sideways. */
html{overflow-x:clip;}
body{font-family:var(--font-body); background:var(--paper); color:var(--ink); line-height:1.6; overflow-x:clip; -webkit-font-smoothing:antialiased;}
a{color:var(--accent-deep);}
::selection{ background:var(--accent-wash); color:var(--ink); }
:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

/* ============ header (interior pages) ============ */
header{color:var(--ink); padding:26px 20px 20px; border-bottom:1px solid var(--rule);}
header::after{content:none;} /* remove legacy wave edge */
.wrap{max-width:880px; margin:0 auto; padding:0 8px;}
header h1{font-family:var(--font-head); font-size:1.5rem; font-weight:700; letter-spacing:-.01em;}
header .sub{opacity:1; color:var(--ink-soft); font-size:.95rem; margin-top:4px;}
header .badge{display:inline-block; background:var(--accent-wash); color:var(--accent-deep); font-family:var(--font-mono); font-weight:700; font-size:.7rem; padding:4px 10px; border-radius:2px; letter-spacing:.08em; text-transform:uppercase; margin-bottom:10px;}

/* ============ nav (tabs / lesson steps) ============ */
nav{position:sticky; top:0; z-index:50; background:var(--paper); border-bottom:1px solid var(--rule); overflow-x:auto;}
nav .wrap{display:flex; gap:2px; align-items:center;}
nav a.home, .home{flex:0 0 auto; display:flex; align-items:center; padding:10px 14px 8px; font-family:var(--font-head); font-size:1rem; text-decoration:none; color:var(--ink); font-weight:700; border-bottom:3px solid transparent;}
nav a.home:hover, .home:hover{color:var(--accent-deep);}
nav .crumb{padding:10px 6px; color:var(--ink-soft); font-size:.9rem;}
nav button{flex:1; min-width:92px; border:none; background:none; padding:12px 6px 10px; font:inherit; font-size:.82rem; color:var(--ink-soft); cursor:pointer; border-bottom:3px solid transparent; white-space:nowrap;}
nav button.active{color:var(--ink); font-weight:700; border-bottom-color:var(--accent);}
nav button.done::after{content:" ✓"; color:var(--accent-deep); font-weight:700;}

/* ---- lesson nav: two rows, so the way out never scrolls off the screen ----
   The old bar put "Menu" as item one of ten in a single horizontally
   scrolling strip. On a phone it disappeared the moment a learner moved past
   step two, and 93% of arrivals are on a phone. Now the exit and the "where
   am I" label sit on their own fixed row; only the steps scroll. */
nav.lessonnav{overflow:visible;}
nav.lessonnav .navtop{display:flex; align-items:center; gap:10px; border-bottom:1px solid var(--rule);}
nav.lessonnav .navtop a.home{flex:0 0 auto; border-bottom:none; padding:9px 10px 9px 6px;
  font-family:var(--font-body); font-size:.9rem; font-weight:700; color:var(--accent-deep);}
nav.lessonnav .navtop a.home:hover{color:var(--ink);}
nav.lessonnav .where{flex:1 1 auto; min-width:0; text-align:right; padding-right:6px;
  font-family:var(--font-mono); font-size:.68rem; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--ink-soft);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
nav.lessonnav .navsteps{display:flex; gap:2px; align-items:center;
  overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none;}
nav.lessonnav .navsteps::-webkit-scrollbar{display:none;}
@media(max-width:520px){
  nav.lessonnav .navtop a.home{font-size:.86rem;}
  nav.lessonnav .where{font-size:.6rem; letter-spacing:.04em;}
}

main{max-width:880px; margin:22px auto 80px; padding:0 14px;}
section{display:none;}
section.visible{display:block; animation:fade .25s ease;}
@keyframes fade{from{opacity:0; transform:translateY(6px);} to{opacity:1; transform:none;}}

h2{font-family:var(--font-head); font-size:1.25rem; font-weight:700; margin-bottom:4px; color:var(--ink);}
.lead{color:var(--ink-soft); margin-bottom:18px; font-size:.95rem;}

/* ============ card — borderless panel, tapering top rule ============ */


/* ============================================================
   NIGHT — the palette Papel & Grafite never had. Only the tokens
   are redefined; every component, mask and diamond rule reads
   from them, so the side-fading works identically after dark.
   ============================================================ */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --paper:#1c1e1b; --paper-raised:#262925; --ink:#eeece3; --ink-soft:#a5a294;
    --accent:#7fb894; --accent-deep:#9ccdad; --accent-wash:rgba(127,184,148,.12);
    --clay:#d99a6c; --clay-deep:#e6b189;
    --rule:rgba(238,236,227,.16);
    --good:#7fb894; --bad:#e0836f; --bad-wash:#33231f; --good-wash:#1e2c23;
    --a2:#c2a463; --b1:#7fa8c2; --b2:#b992ad;
    --green:var(--accent); --green-dark:var(--accent-deep); --green-light:var(--accent);
    --yellow:var(--accent-deep); --blue:var(--accent-deep);
    --muted:var(--ink-soft); --bg:var(--paper); --card:var(--paper-raised); --line:var(--rule);
  }
}

@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .btn.solid,
  :root:not([data-theme="light"]) .btn.big,
  :root:not([data-theme="light"]) .card > .btn:first-of-type{
    background:var(--accent); border-color:var(--accent); color:#15211a;}
  :root:not([data-theme="light"]) .btn.solid:hover,
  :root:not([data-theme="light"]) .btn.big:hover,
  :root:not([data-theme="light"]) .card > .btn:first-of-type:hover{
    background:var(--accent-deep); border-color:var(--accent-deep);}
}

/* ============================================================
   SIDE-FADING BLOCKS
   A raised block never ends in a hard vertical edge. Its fill is
   painted by ::after, which is masked away at the left and right,
   so the panel dissolves back into the paper. The mask is on the
   fill layer only — content sits above it and stays crisp. The
   isolate keeps the -1 layer inside the block instead of sinking
   behind whatever the block is sitting on.
   ============================================================ */
:root{
  --fade:linear-gradient(90deg,transparent 0,#000 6.5%,#000 93.5%,transparent 100%);
  --fade-wide:linear-gradient(90deg,transparent 0,#000 3.5%,#000 96.5%,transparent 100%);
}
.card,.stat,.scard,.tcard,.vcard,.face,header{
  position:relative; isolation:isolate; background:transparent;
}
.card::after,.stat::after,.scard::after,.tcard::after,.vcard::after,.face::after,header::after{
  content:''; position:absolute; inset:0; z-index:-1; background:var(--paper-raised);
  -webkit-mask-image:var(--fade); mask-image:var(--fade);
}
header::after{ -webkit-mask-image:var(--fade-wide); mask-image:var(--fade-wide); }
/* the header hairline should fade out with the fill it belongs to */
header{ border-bottom:none; }
header::before{
  content:''; position:absolute; left:0; right:0; bottom:0; height:1px; background:var(--rule); z-index:0;
  -webkit-mask-image:var(--fade-wide); mask-image:var(--fade-wide);
}

.card{position:relative;  border:none; border-radius:0; padding:22px 24px 20px; margin-bottom:16px;}
.card::before{content:''; position:absolute; top:0; left:6%; right:6%; height:5px; background:var(--accent); z-index:0;
  clip-path:polygon(0% 50%,50% 0%,100% 50%,50% 100%); opacity:.55; transform:translateY(-2.5px);}
.card h3{font-family:var(--font-head); font-size:1.02rem; font-weight:700; margin-bottom:8px;}

.speak{border:none; background:var(--accent); color:var(--paper); border-radius:2px; padding:0; min-width:40px; height:34px; font-size:0; line-height:0; cursor:pointer; vertical-align:middle; display:inline-flex; align-items:center; justify-content:center; margin:1px 0;}
.speak::before{content:''; width:17px; height:17px; display:block; background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 9.5v5h3.5L12 18.5v-13L7.5 9.5H4z' fill='%23000'/%3E%3Cpath d='M15.5 9a4 4 0 0 1 0 6'/%3E%3Cpath d='M18.5 6.5a8 8 0 0 1 0 11'/%3E%3C/svg%3E") center/contain no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 9.5v5h3.5L12 18.5v-13L7.5 9.5H4z' fill='%23000'/%3E%3Cpath d='M15.5 9a4 4 0 0 1 0 6'/%3E%3Cpath d='M18.5 6.5a8 8 0 0 1 0 11'/%3E%3C/svg%3E") center/contain no-repeat;}
.speak.slow{background:transparent; color:var(--ink-soft); border:1.5px solid var(--rule); min-width:44px; margin-left:4px;}
.speak.slow::before{content:'slow'; width:auto; height:auto; background:none; -webkit-mask:none; mask:none; font-family:var(--font-mono); font-size:.68rem; font-weight:700; letter-spacing:.04em; line-height:1;}
.speak:hover{background:var(--accent-deep);} .speak.slow:hover{background:var(--paper-raised); color:var(--ink);}
.speak:active{transform:scale(.95);}
td.sp{white-space:nowrap; text-align:right;}
.soundwrap{display:inline-flex; gap:6px;}
.soundbtn.on{background:var(--accent-wash); border-color:var(--accent); color:var(--accent-deep);}

table{width:100%; border-collapse:collapse; font-size:.95rem;}
th,td{text-align:left; padding:8px 10px; border-bottom:1px solid var(--rule); vertical-align:top;}
th{color:var(--ink-soft); font-size:.78rem; text-transform:uppercase; letter-spacing:.05em; font-weight:700;}
.pt{font-weight:700; color:var(--accent-deep);}

.tip{background:var(--accent-wash); border:none; border-left:2px solid var(--accent); border-radius:0; padding:12px 15px; font-size:.9rem; margin:12px 0;}
.tip b{color:var(--accent-deep);}

.grammarbox{display:grid; grid-template-columns:1fr 1fr; gap:14px;}
@media(max-width:640px){.grammarbox{grid-template-columns:1fr;}}
.conj{background:var(--paper); border:1px solid var(--rule); border-radius:0; padding:14px;}
.conj h4{font-family:var(--font-head); color:var(--accent-deep); margin-bottom:6px; font-size:.95rem;}
.conj div{padding:3px 0; border-bottom:1px dashed var(--rule); display:flex; justify-content:space-between; gap:8px; font-size:.95rem;}
.conj div:last-child{border:none;}
.conjrow{display:flex; justify-content:space-between; gap:8px; padding:3px 0; border-bottom:1px dashed var(--rule); font-size:.95rem;}

/* ============ buttons ============ */
.btn{display:inline-block; border:1.5px solid var(--ink); border-radius:0; padding:10px 20px; font:inherit; font-weight:700; font-size:.9rem; cursor:pointer; background:transparent; color:var(--ink); text-decoration:none;}
.btn:hover{background:var(--ink); color:var(--paper);}
.btn.secondary{background:transparent; color:var(--ink-soft); border-color:var(--rule);}
.btn.secondary:hover{background:var(--ink-soft); color:var(--paper); border-color:var(--ink-soft);}
.btn.big{width:100%; padding:14px; font-size:1.05rem; text-align:center;}
.btn:disabled{opacity:.4; cursor:default;}
/* solid accent variant used for primary CTAs — same markup, extra look via being first .btn in a .card */
.card > .btn:first-of-type, .btn.big{background:var(--ink); border-color:var(--ink); color:var(--paper);}
.card > .btn:first-of-type:hover, .btn.big:hover{background:#1f1e1a; border-color:#1f1e1a;}

.navrow{display:flex; justify-content:space-between; margin-top:20px; gap:10px;}

/* ============ flashcards ============ */
.flash{perspective:1000px; max-width:430px; margin:0 auto;}
.flashcard{position:relative; height:200px; cursor:pointer; transform-style:preserve-3d; transition:transform .45s;}
.flashcard.flipped{transform:rotateY(180deg);}
.face{position:absolute; inset:0; backface-visibility:hidden; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; border:1.5px solid var(--accent); border-radius:0; font-family:var(--font-head); font-size:1.5rem; font-weight:700; padding:16px; text-align:center;}
.face.back{transform:rotateY(180deg); background:var(--accent-wash);}
.face small{font-family:var(--font-body); font-size:.85rem; font-weight:400; color:var(--ink-soft);}
.fc-controls{display:flex; gap:10px; justify-content:center; margin-top:16px;}
.fc-controls .btn.again{background:var(--bad); border-color:var(--bad); color:var(--paper);}
.fc-controls .btn.knew{background:var(--good); border-color:var(--good); color:var(--paper);}
.fc-meta{text-align:center; color:var(--ink-soft); font-size:.85rem; margin-top:10px;}

/* ============ quiz ============ */
.q{margin-bottom:18px;}
.q .stem{font-weight:700; margin-bottom:8px;}
.q .opts{display:grid; gap:8px;}
.q .opts button{text-align:left; border:1.5px solid var(--rule); background:var(--paper); color:var(--ink); border-radius:0; padding:10px 14px; font:inherit; cursor:pointer;}
.q .opts button:hover{border-color:var(--accent);}
.q .opts button.sel{border-color:var(--accent); background:var(--accent-wash); color:var(--ink); font-weight:700;}
.q .opts button.right{border-color:var(--good); background:var(--good-wash); color:var(--ink); font-weight:700;}
.q .opts button.wrong{border-color:var(--bad); background:var(--bad-wash); color:var(--ink);}
.q input[type=text]{width:100%; padding:10px 12px; border:1.5px solid var(--rule); border-radius:0; font:inherit; font-size:1rem; background:var(--paper); color:var(--ink);}
.q input.right{border-color:var(--good); background:var(--good-wash); color:var(--ink);}
.q input.wrong{border-color:var(--bad); background:var(--bad-wash); color:var(--ink);}
.feedback{font-size:.88rem; margin-top:5px; min-height:1.1em;}
.feedback.ok{color:var(--good); font-weight:700;}
.feedback.no{color:var(--bad); font-weight:700;}
.scorebar{background:var(--accent-wash); border:none; border-radius:0; padding:12px 16px; font-weight:700; color:var(--accent-deep); margin:14px 0;}
.wrongitem{border-left:3px solid var(--bad); background:var(--bad-wash); border-radius:0; padding:10px 14px; margin-bottom:8px; font-size:.92rem;}
.wordchips{line-height:2.3;}
.wordchips .pt{margin-right:2px;}
.wordchips .wsep{color:var(--rule); margin:0 6px;}
.lessonhead{margin:24px 0 10px; font-size:1.05rem; font-family:var(--font-head); font-weight:700; color:var(--ink); display:flex; align-items:center; gap:10px;}

/* ============ dialogue ============ */
.dlg{display:flex; flex-direction:column; gap:10px;}
.line, .dlg .row{display:flex; gap:10px; align-items:flex-start;}
.who{flex:0 0 34px; height:34px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:700; color:var(--paper); font-size:.85rem; background:var(--ink-soft);}
.who.a{background:var(--accent);}
.who.b{background:var(--ink);}
.bubble{background:var(--paper); border:1px solid var(--rule); border-radius:0; padding:9px 13px; font-size:1rem;}
.bubble .tr, .bubble small{display:block; color:var(--ink-soft); font-size:.82rem; margin-top:2px;}
.hide-tr .bubble .tr{display:none;}

/* ============ results ============ */
.resgrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:12px; margin:14px 0;}
.stat{ border:none; border-radius:0; padding:14px; text-align:center;}
.stat .num{font-family:var(--font-head); font-size:1.7rem; font-weight:700; color:var(--accent-deep);}
.stat .lbl{font-size:.8rem; color:var(--ink-soft);}
.rate{display:flex; gap:8px; justify-content:center; margin:10px 0 4px;}
.rate button{width:44px; height:44px; border-radius:50%; border:1.5px solid var(--rule); background:var(--paper); font:inherit; font-size:1.1rem; cursor:pointer;}
.rate button.sel{background:var(--accent-wash); border-color:var(--accent); font-weight:700;}
.weak{font-size:.9rem;}
.weak li{margin-left:20px; margin-bottom:3px;}

footer{position:fixed; bottom:0; left:0; right:0; background:var(--paper); border-top:1px solid var(--rule); padding:8px 16px; font-size:.8rem; color:var(--ink-soft); display:flex; justify-content:space-between; z-index:40;}

.banner{background:var(--accent-wash); border:none; border-left:2px solid var(--accent); border-radius:0; padding:14px 16px; margin-bottom:16px; display:flex; gap:10px; align-items:center; flex-wrap:wrap; font-size:.95rem;}
.banner b{color:var(--accent-deep);}
.banner .btn{padding:8px 16px;}

/* ============ tooltips ============ */
[data-tr]{position:relative; cursor:help; border-bottom:1px dotted var(--ink-soft);}
[data-tr]::after{content:attr(data-tr); position:absolute; bottom:calc(100% + 6px); left:0; background:var(--ink); color:var(--paper); padding:6px 11px; border-radius:2px; font-size:.8rem; font-weight:400; line-height:1.35; width:max-content; max-width:min(280px,70vw); opacity:0; visibility:hidden; pointer-events:none; transition:opacity .18s, visibility .18s; z-index:200; white-space:normal;}
[data-tr]:hover::after{opacity:1; visibility:visible; transition-delay:1s;}
.opts button[data-tr]{border-bottom:1.5px solid var(--rule);}

.testcat{margin:20px 0 12px; padding:8px 14px; background:var(--accent-wash); border-left:2px solid var(--accent); border-radius:0; font-size:.95rem; color:var(--accent-deep);}
/* The sound toggles are built by engine.js at runtime. Their size belongs
   HERE and nowhere else: engine.js used to set style.minHeight inline, which
   beats any stylesheet rule without !important and silently made the phone
   rule below a no-op. Removing the inline is the fix; !important would only
   have hidden it. */
.soundbtn{border:1px solid var(--rule); background:var(--paper); border-radius:20px; padding:7px 13px; font:inherit; font-size:.78rem; cursor:pointer; color:var(--ink); min-height:36px;}
.grammarlist td:first-child{font-weight:700; color:var(--accent-deep); white-space:nowrap;}
.gramlink{margin-left:8px; font-size:.82rem; color:var(--accent-deep); text-decoration:none; font-weight:700; white-space:nowrap;}
.gramlink:hover{text-decoration:underline;}

.level{display:inline-block; background:var(--ink); color:var(--paper); font-family:var(--font-mono); font-size:.68rem; font-weight:700; letter-spacing:.04em; border-radius:2px; padding:2px 8px;}
/* One colour per level, from the same ramp the homepage cards and the course
   accordion use, so a level looks the same wherever it appears. The night
   palette redefines these tokens, so the chips follow without extra rules. */
.level.lv-a1{background:var(--accent);}
.level.lv-a2{background:var(--a2);}
.level.lv-b1{background:var(--b1);}
.level.lv-b2{background:var(--b2);}
.lbadge{display:inline-block; background:var(--accent-wash); border:none; color:var(--accent-deep); font-size:.72rem; font-weight:700; border-radius:2px; padding:2px 8px;}

/* ============ histórias ============ */
.grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(250px,1fr)); gap:12px;}
.scard{ border:none; border-radius:0; padding:16px; cursor:pointer; transition:transform .12s;}
.scard:hover{transform:translateY(-2px);}
.scard .num{font-family:var(--font-mono); font-size:.68rem; font-weight:700; letter-spacing:.06em; color:var(--accent-deep); text-transform:uppercase;}
.scard h3{font-family:var(--font-head); font-size:1.05rem; margin:4px 0; font-weight:700;}
.scard p{font-size:.83rem; color:var(--ink-soft);}
.tcard{ border:none; border-radius:0; padding:16px; cursor:pointer; transition:transform .12s;}
.tcard:hover{transform:translateY(-2px);}
.tcard h3{font-family:var(--font-head); font-size:1rem; margin:4px 0; font-weight:700;}
.tcard p{font-size:.83rem; color:var(--ink-soft);}
.story p{font-size:1.08rem; margin-bottom:16px; line-height:1.9;}
.story .sent{cursor:help; border-bottom:1px dotted var(--ink-soft); position:relative;}
.story .sent:hover{background:var(--accent-wash);}
.story .sent::after{content:attr(data-tr); position:absolute; bottom:calc(100% + 6px); left:0; background:var(--ink); color:var(--paper); padding:6px 11px; border-radius:2px; font-size:.8rem; line-height:1.35; width:max-content; max-width:min(320px,75vw); opacity:0; visibility:hidden; pointer-events:none; transition:opacity .18s, visibility .18s; z-index:200; white-space:normal;}
.story .sent:hover::after{opacity:1; visibility:visible; transition-delay:1s;}
.story .sent.playing{background:var(--accent-wash);}
.tr-block{display:none; color:var(--ink-soft); font-size:.92rem; border-left:2px solid var(--rule); padding-left:12px; margin:-8px 0 16px;}
.show-tr .tr-block{display:block;}

/* ============ reference (verbs / words) ============ */
.toolbar{display:flex; gap:10px; flex-wrap:wrap; margin-bottom:16px; align-items:center;}
.toolbar input[type=search]{flex:1; min-width:200px; padding:10px 14px; border:1.5px solid var(--rule); border-radius:0; font:inherit; background:var(--paper);}
.chip{border:1.5px solid var(--rule); background:var(--paper); color:var(--ink); border-radius:20px; padding:6px 14px; font:inherit; font-size:.85rem; cursor:pointer;}
.chip.active{background:var(--ink); border-color:var(--ink); color:var(--paper); font-weight:700;}
.vgrid{display:grid; grid-template-columns:repeat(auto-fill,minmax(270px,1fr)); gap:12px;}
.vcard{ border:none; border-radius:0; padding:14px;}
.vcard h3{font-family:var(--font-head); font-size:1.05rem; color:var(--accent-deep); font-weight:700;}
.vcard .type{font-size:.85rem; color:var(--ink-soft); margin-bottom:8px;}
.vcard .forms div{display:flex; justify-content:space-between; font-size:.9rem; padding:2px 0; border-bottom:1px dashed var(--rule);}
.vcard .forms div:last-child{border:none;}
.vcard .ex{font-size:.85rem; color:var(--ink-soft); margin-top:8px;}
.vcard .ex .pt{font-size:.9rem;}
.count{color:var(--ink-soft); font-size:.85rem; margin-bottom:10px;}

/* ============ celebration / party ============ */
#party{position:fixed; inset:0; background:rgba(49,47,42,.94); z-index:1000; display:none; align-items:center; justify-content:center; text-align:center; color:var(--paper); overflow:hidden;}
#party .inner{position:relative; z-index:2; animation:pop .6s cubic-bezier(.2,1.6,.4,1);}
#party h1, #party h2.ph{font-family:var(--font-head); font-size:3rem; margin-bottom:10px; color:var(--paper);}
#party p{font-size:1.15rem; opacity:.95; margin-bottom:8px;}
#party .btn{margin:8px 6px 0;}
@keyframes pop{from{transform:scale(.3); opacity:0;} to{transform:scale(1); opacity:1;}}
.confetti{position:absolute; top:-20px; width:10px; height:16px; opacity:.9; animation:fall linear forwards;}
@keyframes fall{to{transform:translateY(110vh) rotate(720deg);}}

@media(prefers-reduced-motion:reduce){ .flashcard, .scard, .tcard{transition:none;} #party .inner{animation:none;} }

@media(max-width:640px){
  .card{padding:14px 12px;}
  /* text tables wrap to the card; only genuinely wide tables (5+ columns) scroll sideways */
  .card table{display:table; width:100%; overflow:visible;}
  .card table:has(td:nth-child(5)), .card table:has(th:nth-child(5)){display:block; overflow-x:auto;}
  th,td{padding:7px 5px; font-size:.9rem; word-break:normal; overflow-wrap:anywhere;}
  header h1{font-size:1.3rem;}
  [data-tr]::after{max-width:70vw;}
  /* one tap target per word on a phone — slow playback is the footer toggle */
  .speak.slow{display:none;}
  .speak{min-width:44px; height:44px;}
  /* the fixed bar cost 50px of every screen; on a phone it sits at the end of the page instead */
  footer{position:static; justify-content:center; flex-wrap:wrap; gap:8px 14px; font-size:.88rem; padding:12px 12px 16px;}
  main{margin-bottom:24px;}
  #party h1, #party h2.ph{font-size:2rem;}

  /* ---------- thumbs, not cursors ----------
     Everything below grows a hit area to 44px. Measured on the live build at
     375x667: link lists were 19-21px tall, the grammar-review link 17x17, and
     the secondary buttons 38x38. Nothing here moves anything on a desktop —
     it is all inside this phone-width query. */

  /* A link stacked as a row in a list is only as tall as its own line of text.
     Make the row the target, not the words. */
  .idx a, .pn a, footer a, .card > p > a:only-child{
    display:block; padding:11px 0; min-height:44px;}
  /* historias.html and Reference/PT-grammar.html both style .pagelinks in
     their own <style> block, which sits AFTER the stylesheet link and wins on
     equal specificity. .card .pagelinks a outranks it without editing either
     page — these two lists are how a stranger reaches 40 stories and 60
     grammar chapters, and every row was 27px. */
  .card .pagelinks a{display:block; padding:9px 0; min-height:44px;}
  /* the "read this in Lição 33 · Rumo" links at the foot of all 60 grammar
     pages — inline, 19px, and the only route from an indexed page into the
     course. All 60 carry the same inline .cta rule, so the fix goes here. */
  .card.cta h3 a, .card.cta p a{display:inline-block; padding:11px 8px; min-height:44px;}
  .pn a{padding-left:2px; padding-right:2px;}
  /* the landing page has its own footer with a heavier selector, so it needs
     naming explicitly or it keeps the 17px rows */
  footer.site-footer a{display:inline-block; padding:11px 0; min-height:44px; margin-right:20px;}
  /* the wordmark in the course top bar is the way home */
  .topbar > a{display:inline-flex; align-items:center; min-height:44px;}
  /* the public teaser on a paid lesson — these are the pages Google indexes,
     so for most strangers this list IS the navigation */
  #teaser li a, #teaser p a{display:inline-block; padding:10px 0; min-height:44px;}

  /* "📖 review this grammar" sits in the test feedback — exactly where a
     learner has just got something wrong and wants the explanation. It was the
     smallest thing on the site. */
  .gramlink{display:inline-flex; align-items:center; min-height:44px; padding:0 10px; margin-left:4px;}

  /* The way out of a lesson, on every lesson and every exam: 41px. */
  nav.lessonnav .navtop a.home{min-height:44px; padding-top:11px; padding-bottom:11px;}

  /* "📖 review this grammar" was tall enough but only 37px wide. */
  .gramlink{min-width:44px; justify-content:center;}

  /* Secondary buttons were six pixels short. */
  .btn{display:inline-flex; align-items:center; justify-content:center; min-height:44px;}

  /* The dictionary and verb filters are chips in a wrapping row — easy to miss
     by a few pixels, and they are the only way to narrow 2,207 words. */
  .chip{min-height:44px; padding:6px 15px; display:inline-flex; align-items:center;}

  /* the sound toggles and anything else engine.js puts in the lesson footer */
  footer button, .soundbtn{min-height:44px; padding:8px 14px;}

  /* ---------- story translation tooltips ----------
     The per-sentence translation is a hover tooltip. A phone has no hover, but
     the first tap on an element fires a synthetic one, so it DOES appear on
     touch — verified in a touch context. Anchored to the sentence it runs off
     the right edge: measured on Lição 1 at 375px, 7 of 76 tooltips overhang,
     the worst by 117px, and since v36 switched to overflow-x:clip that
     overhang is silently CUT OFF rather than scrollable.
     Fix: at phone width anchor it to the paragraph instead of the sentence
     (position:static on .sent makes the ::after resolve against the <p>), and
     let it span the full column. Never clipped, always in the same place,
     which on a narrow screen reads better than chasing the exact word. */
  /* Every sentence in a story is a tap target — tapping it is how the
     translation appears, and it is the single most-used gesture in the
     section. Measured 23px: the sentence box is only as tall as its own line
     of text. Padding grows the hit area; the line-height grows with it so two
     stacked sentences never overlap, which would just move the mis-tap
     somewhere else. Reads better on a phone anyway. */
  .story p{position:relative; line-height:2.5;}
  .story .sent{position:static; padding:8px 0;}
  .story .sent::after{left:0; right:0; width:auto; max-width:none;
    bottom:calc(100% + 6px); text-align:left;}

  /* Uppercase monospace is the least forgiving combination at small sizes, and
     this badge now carries the level name as well. */
  header .badge{font-size:.84rem; letter-spacing:.06em;}
}
