/* The header's account corner — the credit badge and the profile chip.
   /assets/js/credits.js links this file AND system.css itself, so the nine
   canvas tools get the same chip without loading site.css, whose body/card/grid
   rules would fight their own stylesheets. One copy, wherever the chip is
   mounted: a second hand-kept copy drifts the way two Persian normalisers do.

   Migrated to the design system. The palette used to be re-declared here as
   --ac-* because canvas pages never load site.css's :root; now credits.js puts
   data-surface on each element it creates, and system.css supplies the tokens
   with no second copy to keep in step. system.css paints nothing without
   .y-page, so linking it into a canvas page changes nothing but this chip.

   The dark host is not a variant of the chip — it is a different surface.
   .acct-dark is gone; the mount table decides, and the trigger carries
   data-surface="dark" while the panel it opens declares "paper" for itself.
   That split was already the intent: only the trigger sits on the navy band. */

/* The standalone credit pill is gone. It was a second control beside the chip
   for the same idea — who you are, and what you have — and the wallet moved
   inside the chip on 2026-09-02. Nothing has built a `.credit-badge` since;
   its rules, and the ∞ it printed with a text glyph, went with it. The one
   line that still names the class is a flex-order rule in index.html, kept
   because it is harmless and costs a selector. */

/* ---- the corner: one icon ---- */
.acct-wrap{position:relative;}
/* 44px is the floor for anything a thumb has to hit. The chip was 38 tall,
   which is the one control on the whole site that a corridor tap could miss. */
.acct-chip.icon{
  inline-size:44px;block-size:44px;min-block-size:44px;padding:0;
  display:inline-flex;align-items:center;justify-content:center;position:relative;
  background:transparent;border:1px solid var(--y-control);
  border-radius:var(--y-radius);cursor:pointer;color:var(--y-text);
  font:inherit;line-height:1;text-decoration:none;
}
.acct-chip.icon:hover{border-color:var(--y-accent);color:var(--y-accent);}
.acct-chip.icon:focus-visible{outline:3px solid var(--y-accent);outline-offset:2px;}
.acct-chip.icon .av{
  inline-size:23px;block-size:23px;display:block;background:none;color:inherit;}
.acct-chip.icon .av svg{inline-size:100%;block-size:100%;display:block;}
/* SIGNED OUT, AND NOTHING ELSE. It marked an empty wallet as well until
   2026-09-05 -- «remove the orange dot on profile icon when logged in» -- and
   one mark meaning both «there is a door here» and «your credit ran out» meant
   neither reliably. A signed-in person already has an account; the balance is
   named in words inside the sheet, where there is room for it. */
.acct-chip.icon .dot{
  position:absolute;inset-block-start:6px;inset-inline-end:6px;
  inline-size:8px;block-size:8px;border-radius:50%;
  background:var(--y-accent);border:2px solid var(--y-ground);
  /* NO ENTRANCE ANIMATION, DELIBERATELY, and it took two attempts to get here.
     First `.34s … .5s backwards`: `backwards` applies the from-frame during the
     delay, and an animation clock does not advance while rendering is
     suspended -- a tab opened in the background, a hidden window, a phone with
     the browser behind something else. Measured in that state the dot sat at
     opacity 0, 2x2, for as long as it was watched. Dropping `backwards` did not
     help either: an animation in the `running` state still applies its own
     0% frame, and at a clock stuck on 0 that frame IS opacity 0.
     A badge whose existence depends on an animation having run is a badge that
     can silently not exist -- the same shape as rAF never firing in a
     background tab, which cost the check-in door its step and the install bar
     its reveal. The dot arrives with the corner it belongs to, which is itself
     inserted in one go at boot, so nothing here appears abruptly either. */
  opacity:1;}

/* ---- the plans ----
   One card per plan, and a plan nobody can take says so ON ITSELF rather than
   being a disabled button with no explanation beside it. `.off` dims the card
   and not the words that explain why it is off: an unreadable reason is worse
   than no reason. */
.ysh-plans{display:grid;gap:10px;margin-block-end:12px;}
.ysh-plan{display:grid;gap:4px;padding:14px 14px 12px;border-radius:var(--y-radius);
  border:1px solid var(--y-control);background:var(--y-panel);}
.ysh-plan.off{opacity:.72;}
.ysh-plan b{font-size:15px;color:var(--y-text);}
.ysh-plan .ysh-plan-n{font-size:13px;color:var(--y-muted);line-height:1.7;}
.ysh-plan .ysh-plan-w{font-size:12.5px;color:var(--y-teal-ink);font-weight:700;}
/* A PRICE IS NOT A CAVEAT. .ysh-plan-w is the «why you cannot have this» line —
   «قبلاً استفاده شده», «به‌زودی» — and a price rendered in it was styled as an
   apology at 12.5px. This is a fact about the plan and the last thing read
   before a button that leaves for a bank, so it is the size of the plan's own
   name and in the text colour. */
.ysh-plan .ysh-plan-p{font-size:15px;color:var(--y-text);font-weight:700;
  font-variant-numeric:tabular-nums;}
.ysh-plan button{margin-block-start:8px;}
/* The card the person can actually act on is the one with a border that says
   so; the others are quiet. State is never colour alone here either -- the
   button's own words differ («شروع کنید» against «در دسترس نیست»). */
.ysh-plan:not(.off){border-color:var(--y-accent);}
/* A DISCOUNT (2026-10-12): the old price struck through and quiet, the new one
   in the price's own weight, and the line that says which code did it. */
.ysh-plan .ysh-was{color:var(--y-muted);font-weight:400;text-decoration:line-through;
  margin-inline-start:10px;font-size:13.5px;}
.ysh-plan .ysh-plan-d{font-size:12.5px;color:var(--y-teal-ink);font-weight:700;}
.ysh-link{background:none;border:0;padding:0;min-block-size:44px;color:var(--y-text);
  font:inherit;font-size:13.5px;text-decoration:underline;text-underline-offset:3px;cursor:pointer;}
.ysh-link:hover{color:var(--y-accent-ink, var(--y-text));}
.ysh-codebtn{display:flex;align-items:center;gap:10px;inline-size:100%;min-block-size:46px;
  margin-block:2px 10px;padding:0 14px;border:1px dashed var(--y-control);border-radius:var(--y-radius);
  background:transparent;color:var(--y-text);font:inherit;font-size:14px;font-weight:600;
  text-align:start;cursor:pointer;transition:border-color .16s,background .16s;}
.ysh-codebtn svg{inline-size:20px;block-size:20px;flex:0 0 auto;fill:none;stroke:var(--y-accent);
  stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;}
.ysh-codebtn span{flex:1 1 auto;}
/* DRAWN pointing left, which is forward on this sheet. A lone «›» in its own
   flex item is not mirrored and pointed back the way the reader came. */
.ysh-codebtn svg.chev{inline-size:18px;block-size:18px;stroke:var(--y-muted);stroke-width:2;}
.ysh-codebtn:hover{border-color:var(--y-accent);background:var(--y-raise);}
.ysh-codebtn:focus-visible{outline:3px solid var(--y-accent);outline-offset:2px;}
.ysh-code{margin-block:2px 10px;}
.ysh-code label{display:block;font-size:13px;color:var(--y-muted);margin-block-end:6px;}
.ysh-code-row{display:flex;gap:8px;align-items:stretch;}
.ysh-code-row input{flex:1 1 auto;min-inline-size:0;}
.ysh-code-row .mini{flex:0 0 auto;margin:0;}
.ysh-code-on{font-size:13px;color:var(--y-text);margin-block:2px 8px;display:flex;
  align-items:center;gap:8px;flex-wrap:wrap;}

/* ═══ the sheet ═══════════════════════════════════════════════════════
   It always declares data-surface="paper" on itself, so it reads the same
   whichever header the trigger is sitting in.

   IT IS ANCHORED TO THE BOTTOM EDGE, and that is load-bearing: when the credit
   packages open BELOW the profile the sheet grows, and because the bottom is
   pinned the growth moves the TOP of it upward. That upward movement is what
   Amin asked for, and it is the layout doing it rather than a second animation
   that would have to be kept in step with the first. */
.ysh-scrim{
  position:fixed;inset:0;z-index:998;background:rgba(20,17,16,.52);
  animation:ysh-fade .22s ease;}
.ysh-scrim.out{animation:ysh-fade .2s ease reverse forwards;}
@keyframes ysh-fade{from{opacity:0}}
/* The page behind a modal must not scroll. overflow on BODY only — putting it
   on <html> once made the whole site unscrollable, because clip on one axis
   forces the other out of visible and on the root that axis is the viewport's
   own scroll container. */
body.ysh-open{overflow:hidden;}
.ysheet{
  position:fixed;inset-inline:0;inset-block-end:0;z-index:999;
  max-block-size:88dvh;display:flex;flex-direction:column;
  background:var(--y-panel);color:var(--y-text);
  border-block-start:1px solid var(--y-rule);
  border-start-start-radius:20px;border-start-end-radius:20px;
  box-shadow:0 -14px 40px rgba(20,17,16,.30);
  animation:ysh-up .26s cubic-bezier(.2,.8,.2,1);text-align:start;}
.ysheet.out{animation:ysh-up .2s ease reverse forwards;}
@keyframes ysh-up{from{transform:translateY(22px);opacity:0}}
.ysheet:focus{outline:none;}
/* A sheet wider than a phone is a dialog pretending to be a sheet. */
@media (min-width:620px){
  .ysheet{inset-inline:auto 24px;inline-size:400px;inset-block-end:24px;
    border-radius:20px;}
}
.ysh-grab{
  inline-size:44px;block-size:4px;border-radius:999px;background:var(--y-rule-2);
  margin:10px auto 0;flex:0 0 auto;}
.ysh-body{padding:6px 20px 20px;overflow-y:auto;-webkit-overflow-scrolling:touch;}

.ysh-head{display:flex;align-items:center;gap:12px;padding-block:12px 4px;}
.ysh-av{
  inline-size:42px;block-size:42px;flex:0 0 auto;border-radius:var(--y-radius);
  background:var(--y-accent);color:var(--y-on-accent);
  display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;}
.ysh-who{display:flex;flex-direction:column;gap:2px;min-inline-size:0;flex:1 1 auto;}
.ysh-who b{font-size:15.5px;font-weight:700;line-height:1.45;}
.ysh-sub{color:var(--y-muted);font-size:12.5px;word-break:break-all;}
.ysh-sub.ltr{direction:ltr;unicode-bidi:isolate;text-align:start;}
/* 44, like everything else a thumb has to hit. It measured 34 and 38 -- the
   two controls in this sheet that a corridor tap could miss, and the pencil is
   the one that unlocks the fields, so missing it reads as the field being
   permanently locked. */
.ysh-x{
  margin-inline-start:auto;flex:0 0 auto;inline-size:44px;block-size:44px;
  border:0;background:transparent;color:var(--y-muted);font-size:22px;line-height:1;
  cursor:pointer;border-radius:var(--y-radius);}
.ysh-x:hover{background:var(--y-raise);color:var(--y-text);}

/* ---- the balance, and the way to more of it ---- */
.ysh-credit{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin-block-start:14px;padding:13px 14px;border-radius:var(--y-radius);
  background:var(--y-raise);border:1px solid var(--y-rule);font-size:13.5px;}
.ysh-credit b{font-weight:700;}
/* TEAL, not the brand orange. Orange is this site's «do the next step» colour
   and buying credit is not the next step of anything on the page behind the
   sheet; giving it the accent would make it the loudest thing in the panel. */
.ysh-buy{
  margin-inline-start:auto;border:1px solid var(--y-teal);background:transparent;
  color:var(--y-teal-ink);font:inherit;font-size:13px;font-weight:700;
  padding:9px 15px;min-block-size:44px;border-radius:var(--y-radius-btn);cursor:pointer;}
.ysh-buy:hover{background:var(--y-teal);color:#fff;}
.ysh-buy.on{background:var(--y-teal);color:#fff;}
/* 0fr -> 1fr is the one height transition that does not need a magic pixel
   number: the row resolves to the content's own height at 1fr. The inner box
   needs min-block-size:0 or the grid refuses to shrink it. */
.ysh-packs{display:grid;grid-template-rows:0fr;transition:grid-template-rows .34s
  cubic-bezier(.2,.8,.2,1);}
.ysh-packs.open{grid-template-rows:1fr;}
.ysh-packs-in{overflow:hidden;min-block-size:0;}
.ysh-pack{
  inline-size:100%;display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-block-start:8px;padding:13px 14px;min-block-size:44px;
  border:1px solid var(--y-rule-2);border-radius:var(--y-radius);
  background:var(--y-field);color:var(--y-text);font:inherit;font-size:13.5px;cursor:pointer;}
.ysh-pack:hover{border-color:var(--y-teal);}
.ysh-pack:disabled{opacity:.55;cursor:default;}
.ysh-pack b{font-weight:700;}
.ysh-pack span{color:var(--y-muted);}

/* ---- the fields, locked until the pencil ---- */
.ysh-fields{margin-block-start:18px;padding-block-start:14px;
  border-block-start:1px solid var(--y-rule);}
.ysh-fhead{display:flex;align-items:center;justify-content:space-between;
  font-size:13px;font-weight:700;color:var(--y-text);}
.ysh-pencil{
  inline-size:44px;block-size:44px;display:inline-flex;align-items:center;
  justify-content:center;border:1px solid var(--y-control);background:transparent;
  color:var(--y-muted);border-radius:var(--y-radius);cursor:pointer;}
.ysh-pencil svg{inline-size:18px;block-size:18px;}
.ysh-pencil:hover{border-color:var(--y-accent);color:var(--y-accent);}
.ysh-fields.editing .ysh-pencil{border-color:var(--y-accent);color:var(--y-accent);
  background:var(--y-raise);}
/* the pencil belongs to its own field, so it must not stretch with the row */
.ysh-erow .ysh-pencil{flex:0 0 auto;}
.ysh-fields label{display:block;font-size:12.5px;font-weight:700;color:var(--y-text);
  margin-block:12px 5px;}
.ysh-fields input{
  inline-size:100%;padding:11px;border:1px solid var(--y-control);
  border-radius:var(--y-radius);font:inherit;font-size:16px;
  background:var(--y-field);color:var(--y-text);min-block-size:44px;}
/* A LOCKED FIELD MUST LOOK LOCKED. readonly alone is invisible, so the first
   thing a person does is tap it, get a caret, type, and find nothing saved. */
.ysh-fields input[readonly]{background:transparent;border-color:var(--y-rule);
  color:var(--y-ink2,var(--y-text));cursor:default;}
.ysh-fields input:focus{outline:3px solid var(--y-accent);outline-offset:2px;
  border-color:var(--y-accent);}
.ysh-fields input.ltr{direction:ltr;unicode-bidi:isolate;text-align:start;}
.ysh-erow{display:flex;align-items:center;gap:8px;}
.ysh-erow input{flex:1 1 auto;min-inline-size:0;}
.ysh-verify{
  flex:0 0 auto;border:1px solid var(--y-control);background:transparent;
  color:var(--y-text);font:inherit;font-size:12.5px;font-weight:700;
  padding:0 12px;min-block-size:44px;border-radius:var(--y-radius);cursor:pointer;
  white-space:nowrap;}
.ysh-verify:hover{border-color:var(--y-accent);color:var(--y-accent);}
.ysh-ok{flex:0 0 auto;inline-size:26px;block-size:26px;display:inline-flex;
  align-items:center;justify-content:center;color:var(--y-teal-ink);}
.ysh-ok svg{inline-size:18px;block-size:18px;}
/* The code field opens directly under the button that asked for it, the same
   0fr/1fr growth the packages use. */
.ysh-vbox{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .32s cubic-bezier(.2,.8,.2,1);}
.ysh-vbox.open{grid-template-rows:1fr;}
.ysh-vbox-in{overflow:hidden;min-block-size:0;}
.ysh-spam,.ysh-hint{color:var(--y-muted);font-size:12px;margin-block:8px 0;line-height:1.7;}
.ysh-foot{margin-block-start:18px;padding-block-start:14px;
  border-block-start:1px solid var(--y-rule);}
/* the two ways to ask for another code, side by side and equal: neither road is
   the "real" one, and the cooldown that applies is per channel on the server */
.ysh-resend{display:flex;gap:16px;flex-wrap:wrap;margin-block-start:12px;}
.ysh-body .linkish{background:none;border:0;color:var(--y-accent);font:inherit;
  font-size:12.5px;text-decoration:underline;cursor:pointer;padding:0;
  min-block-size:44px;}

/* the buttons and the notes, unchanged in behaviour from the panel this
   replaced — same classes, so the phone-change screens needed no rewrite */
.ysh-body .acts{display:flex;gap:8px;align-items:center;margin-block-start:14px;}
.ysh-body .mini{
  border-radius:var(--y-radius-btn);padding:11px 18px;font:inherit;font-size:13px;
  font-weight:700;cursor:pointer;border:1px solid transparent;min-block-size:44px;}
.ysh-body .mini.go{background:var(--y-accent);color:var(--y-on-accent);}
.ysh-body .mini.go:hover{filter:brightness(1.08);}
.ysh-body .mini.ghost{background:transparent;color:var(--y-muted);border-color:var(--y-control);}
.ysh-body .mini.ghost:hover{border-color:var(--y-accent);color:var(--y-text);}
.ysh-body .note{
  font-size:12.5px;border-radius:var(--y-radius);padding:9px 12px;
  margin-block-start:10px;display:none;border-inline-start:4px solid transparent;}
/* An error and a confirmation must be told apart with the eyes closed to
   colour: the rule is on opposite edges and the marks differ. The marks are
   drawn from --y-mk-* in system.css rather than typed as "⚠ " / "✓ ". */
.ysh-body .note.err::before,.ysh-body .note.ok::before{
  content:"";display:inline-block;inline-size:1em;block-size:1em;
  vertical-align:-.16em;margin-inline-end:.45em;background:currentColor;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;}
.ysh-body .note.err{display:block;background:var(--y-raise);
  border-inline-start-color:var(--y-accent);color:var(--y-text);}
.ysh-body .note.err::before{-webkit-mask-image:var(--y-mk-warn);mask-image:var(--y-mk-warn);}
.ysh-body .note.ok{display:block;background:var(--y-raise);
  border-inline-start-color:var(--y-text);color:var(--y-text);}
.ysh-body .note.ok::before{-webkit-mask-image:var(--y-mk-tick);mask-image:var(--y-mk-tick);}

@media (prefers-reduced-motion:reduce){
  .ysheet,.ysh-scrim{animation:none;}
  .ysh-packs,.ysh-vbox{transition:none;}
}

/* On a band this system does not own — the interview guide's masthead is a
   navy gradient running to #20487A — the chip stops being transparent and
   paints its own ground. Transparent means the effective background is
   someone else's colour, and the dark tokens are tuned for #141110: measured
   over that gradient the muted label fell to 3.44:1, the accent to 2.7 and the
   control border to 1.94. Painting its own plate makes the chip's contrast a
   fact instead of a hope about a stylesheet we do not control.
   On paper the chip stays transparent, because both light hosts are white or
   near-white and every token holds there. */
[data-surface="dark"].acct-chip{background:var(--y-ground);}

/* The chip is appended last, so it needs something to push it to the far edge
   on headers that have no spacer of their own. */
.acct-gap{flex:1 1 auto;min-inline-size:0;}

@media (prefers-reduced-motion:no-preference){
  .acct-chip,.ysh-body .mini,.ysh-buy,.ysh-verify,.ysh-pencil,.ysh-pack{
    transition:border-color .16s ease,color .16s ease,background .16s ease,filter .16s ease;}
}

/* The chip no longer moves into the menu on a phone, so the rules that dressed
   it as a full-width row in there are gone with the code that put it there. It
   is a 44px icon in the bar at every width -- the same place «ورود» sits when
   nobody is signed in. */
/* A WAITING BUTTON KEEPS ITS WORD AND GROWS THREE DOTS. Swapping the label for
   a spinner makes the control read as broken -- Amin's rule, and the reason the
   panel's own busy state works the same way. The dots are ::after so no markup
   changes, and they are the only thing that moves. */
.ysheet button.ysh-busy{position:relative;opacity:.82;cursor:default}
.ysheet button.ysh-busy::after{content:'';display:inline-block;inline-size:1.1em;
  text-align:start;animation:ysh-dots 1.1s steps(4,end) infinite}
@keyframes ysh-dots{0%{content:''}25%{content:'·'}50%{content:'··'}75%{content:'···'}}
@media (prefers-reduced-motion:reduce){
  .ysheet button.ysh-busy::after{animation:none;content:'···'}
}

/* the bootcamp groups on the profile: read-only chips under the phone */
.ysh-tlab{display:block;font-size:12.5px;font-weight:700;color:var(--y-text);margin-block:12px 6px;}
.ysh-teams{display:flex;flex-wrap:wrap;gap:6px;}
.ysh-team{display:inline-flex;align-items:center;gap:7px;padding:5px 11px 5px 6px;
  border:1px solid var(--y-rule);border-radius:999px;background:var(--y-raise);
  font-size:13px;color:var(--y-text);line-height:1.6;}
.ysh-team b{inline-size:22px;block-size:22px;display:grid;place-items:center;border-radius:50%;
  background:var(--y-ground);color:var(--y-accent);font-size:12px;font-weight:700;}
