/* ===========================================================================
   ALOKE CONSOLE — the owner-facing pair (/owner and /loyalty).
   ===========================================================================
   Loaded LAST in each page's head, after auth.css and the page's own sheet,
   so everything here wins by order and nothing needs !important.

   WHAT THIS FILE IS: one design system for the two consoles a shop owner
   uses — a token layer that re-values what auth.css declares, and a component
   pass over shapes that already exist in the markup.

   WHAT IT IS NOT, AND THIS IS THE WHOLE DISCIPLINE: it does not change a
   single line of behaviour. `owner.js` is 16,000 lines of argued decisions and
   `owner.css` is another 3,000; a redesign that rewrote them would be a
   rewrite wearing a redesign's name, and every one of those arguments would
   have to be won again. Nothing here adds a class, renames one, or needs the
   HTML to move. The admin/super consoles, the till and the customer pages do
   not load this file and keep their own look.

   ---------------------------------------------------------------------------
   THE DESIGN DIRECTION, and where it came from.

   The generated recommendation for «business owner dashboard» was
   Data-Dense Dashboard — space-efficient grid, KPI tiles, tables that read
   across, minimal chrome. That is right for this product and it is the spine
   of what follows.

   THREE OF ITS RECOMMENDATIONS ARE REFUSED HERE, on purpose:

     * ITS PALETTE (blue #1E40AF). Aloke's colour is a deep purple, and it is
       not decoration — it is the customer's loyalty card, the wallet pass, the
       landing page and the app icon. A console in another colour would be the
       one screen in the product that does not look like the product.
       KEPT: the palette's STRUCTURE — semantic roles rather than raw hex at
       the call site, a muted foreground that is still 4.5:1, a destructive
       that is not the accent, an explicit ring.

     * ITS TYPE PAIRING (Fira Sans / Fira Code). Fira Sans has no Arabic
       coverage at all, and this console is Arabic first. Readex Pro — already
       loaded — is a variable family drawn for Arabic AND Latin, which is why
       it was chosen and why it stays. KEPT: the idea behind the mono half —
       figures need tabular, LTR-isolated treatment, which is done below with
       font features rather than a second family.

     * ITS PATTERN («Enterprise Gateway»: hero video, client logos, contact
       sales). That is a marketing page for a product nobody has bought yet.
       This is a signed-in console for somebody who already owns the shop.

   ---------------------------------------------------------------------------
   WHAT ACTUALLY CHANGED, and why each one:

   1. A REAL TYPE SCALE. Sizes were arbitrary across two sheets; scanning a
      dense screen depends on the eye trusting that bigger means higher. One
      modular scale, six steps, used everywhere.
   2. AN ELEVATION SCALE INSTEAD OF ONE SHADOW. Three levels that say how far
      off the page a thing is: a card rests, a popover floats, a dialog sits
      above everything. One shadow for all three flattens the hierarchy it is
      supposed to build.
   3. DENSITY. A dashboard is scanned, not read: the row rhythm tightens and
      the section padding comes in, WITHOUT touching the 44px minimum on
      anything a thumb has to hit.
   4. STATUS IS NEVER COLOUR ALONE. Every state that mattered was a border
      colour; each now carries a tinted ground and a weighted label, so it
      survives a colour-blind reader and a cheap monitor in a shop.
   5. NUMBERS ARE FIGURES, NOT WORDS. Tabular, LTR-isolated, and the same
      treatment everywhere one appears — a total, a tile, a table cell.
   6. DARK MODE, for the first time. Owners work evenings; every token has a
      dark value and the accent lightens rather than inverting.
   =========================================================================== */

:root {
  /* ---- GROUND AND INK ---------------------------------------------------
     A near-white with a breath of the brand's own violet in it rather than a
     dead grey: the neutral is CHOSEN, and against a pure-white card it reads
     as a considered surface instead of an unpainted one. */
  --bg: #F6F4FA;
  --surface: #FFFFFF;
  --surface-2: #FBFAFD;      /* table stripes, inset wells, disabled fields */
  --ink: #1F1830;
  --ink-2: #443B57;          /* secondary body — still 7:1 on --surface */
  --muted: #675D7A;          /* 4.6:1 on --surface: the floor, not a target */
  --line: #E7E2F0;
  --line-strong: #D6CEE6;    /* a border that has to be seen, not felt */

  /* ---- BRAND ------------------------------------------------------------ */
  --accent: #5B2C91;         /* Aloke purple — the customer's own card */
  --accent-press: #46216F;
  --accent-hover: #6A36A6;
  --accent-weak: #F2ECFA;
  --accent-weak-2: #E6DBF6;  /* the selected row, one step firmer */
  /* THE INK THAT GOES ON THE ACCENT, as a token and not as a literal at each
     call site. This exists because writing `color: #fff` twice was already a
     bug: the dark-mode accent is a LIGHT purple, so white on it measures
     2.77:1 — and the two places that sit on the accent (the primary button and
     the selected tab) were fixed one at a time, which is exactly how the third
     one gets missed. One token, and there is nothing left to forget. */
  --on-accent: #FFFFFF;

  /* ---- STATUS. Each is a PAIR: a ground to fill and an ink to write on it,
     so a state is never carried by a hairline alone. -------------------- */
  --ok: #1F7A4D;      --ok-weak: #E8F5EE;
  --warn: #8A5A00;    --warn-weak: #FDF3E0;
  --danger: #B4232B;  --danger-weak: #FDEDEE;
  --info: #1B5E8A;    --info-weak: #E7F2F9;

  /* ---- TYPE SCALE. Six steps, ~1.2 ratio. Nothing outside this list. ---- */
  --t-xs: 12px;    /* legal lines, table sub-labels */
  --t-sm: 13px;    /* hints, chips, secondary rows */
  --t-md: 15px;    /* body — the reading size */
  --t-lg: 17px;    /* card titles */
  --t-xl: 21px;    /* section headings */
  --t-2xl: 27px;   /* the page's one heading, and stat figures */
  --lh-tight: 1.35;
  --lh-body: 1.65;   /* Arabic sets taller than Latin; this is the floor */

  /* ---- RADII ------------------------------------------------------------ */
  --r-card: 14px;
  --r-btn: 10px;
  --r-chip: 8px;

  /* ---- ELEVATION. Three levels, and each one MEANS something. ---------- */
  --e-rest: 0 1px 2px rgba(31, 24, 48, .04);
  --e-card: 0 1px 2px rgba(31, 24, 48, .04), 0 4px 14px rgba(31, 24, 48, .05);
  --e-float: 0 12px 34px rgba(31, 24, 48, .13);
  --card-shadow: var(--e-card);       /* the name older rules already use */
  --overlay-shadow: var(--e-float);

  --ring: 0 0 0 3px rgba(91, 44, 145, .18);

  /* ---- MOTION. One duration for everything is why interfaces feel cheap:
     a hover is not a panel opening. Two durations and one easing. -------- */
  --dur-fast: 120ms;   /* colour, border — a response to the pointer */
  --dur-move: 200ms;   /* something that changes size or position */
  --ease: cubic-bezier(.2, 0, 0, 1);
}

/* ===========================================================================
   DARK MODE — new, and the reason is the shift pattern: an owner does the
   week's numbers after closing, on a phone, in a room with the lights down.
   The accent LIGHTENS rather than inverting: a purple that works on white is
   a bruise on near-black, and the brand has to survive both grounds.
   =========================================================================== */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #16121F;
    --surface: #1E1A29;
    --surface-2: #241F31;
    --ink: #F2EFF7;
    --ink-2: #CFC7DD;
    --muted: #A79CBB;          /* 4.9:1 on --surface */
    --line: #322B42;
    --line-strong: #453C59;

    --accent: #B18AE0;         /* lightened; the pressed state goes brighter */
    --accent-press: #C7A6ED;
    --accent-hover: #C09AE7;
    --accent-weak: #2A2140;
    --accent-weak-2: #362A52;
    /* Near-black on the lightened purple: 6.5:1, where white would be 2.8. */
    --on-accent: #1B1226;

    --ok: #6FD3A0;     --ok-weak: #17301F;
    --warn: #E7B565;   --warn-weak: #33260F;
    --danger: #F19097; --danger-weak: #3A1A1D;
    --info: #7FC2E8;   --info-weak: #14293A;

    --e-rest: 0 1px 2px rgba(0, 0, 0, .5);
    --e-card: 0 1px 2px rgba(0, 0, 0, .45), 0 4px 14px rgba(0, 0, 0, .35);
    --e-float: 0 12px 34px rgba(0, 0, 0, .6);
    --ring: 0 0 0 3px rgba(177, 138, 224, .3);
  }
}

/* THE SAME VALUES UNDER AN EXPLICIT CHOICE. Three states, not two: a
   stamped `dark` must win over a light operating system exactly as the
   block above lets a stamped `light` win over a dark one. Without this,
   a theme toggle would do nothing for the half of readers whose OS is
   already set the other way — which is how a toggle ships broken.
   The two bodies are IDENTICAL and a test holds them to it. */
:root[data-theme="dark"] {
    --bg: #16121F;
    --surface: #1E1A29;
    --surface-2: #241F31;
    --ink: #F2EFF7;
    --ink-2: #CFC7DD;
    --muted: #A79CBB;          /* 4.9:1 on --surface */
    --line: #322B42;
    --line-strong: #453C59;

    --accent: #B18AE0;         /* lightened; the pressed state goes brighter */
    --accent-press: #C7A6ED;
    --accent-hover: #C09AE7;
    --accent-weak: #2A2140;
    --accent-weak-2: #362A52;
    /* Near-black on the lightened purple: 6.5:1, where white would be 2.8. */
    --on-accent: #1B1226;

    --ok: #6FD3A0;     --ok-weak: #17301F;
    --warn: #E7B565;   --warn-weak: #33260F;
    --danger: #F19097; --danger-weak: #3A1A1D;
    --info: #7FC2E8;   --info-weak: #14293A;

    --e-rest: 0 1px 2px rgba(0, 0, 0, .5);
    --e-card: 0 1px 2px rgba(0, 0, 0, .45), 0 4px 14px rgba(0, 0, 0, .35);
    --e-float: 0 12px 34px rgba(0, 0, 0, .6);
    --ring: 0 0 0 3px rgba(177, 138, 224, .3);
}


/* ===========================================================================
   TYPOGRAPHY
   =========================================================================== */
body { font-size: var(--t-md); line-height: var(--lh-body); color: var(--ink); }

h1 { font-size: var(--t-2xl); line-height: var(--lh-tight); letter-spacing: -.01em; }
.section > h2 { font-size: var(--t-xl); line-height: var(--lh-tight); letter-spacing: -.005em; }
.section-sub, .sub { font-size: var(--t-sm); color: var(--muted); line-height: var(--lh-body); }

/* HEADINGS DO NOT ORPHAN THEIR LAST WORD. An Arabic heading that drops one
   word onto its own line reads as a mistake, and `balance` is exactly the
   property for a two-or-three-line title. */
h1, .section > h2 { text-wrap: balance; }

/* EVERY FIGURE IN THIS PRODUCT IS SET THE SAME WAY, wherever it appears.
   Tabular so a column of totals lines up; ISOLATED so the bidi algorithm
   cannot reorder «316×120» into «120×316» or push a currency mark to the
   wrong end of a right-to-left line. */
.stat-num, .num, td.n, .money, .kpi-v {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
  direction: ltr;
  unicode-bidi: isolate;
}

/* ===========================================================================
   THE SHELL
   =========================================================================== */
body { background: var(--bg); }

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  box-shadow: none;                     /* the line does this job, not a shadow */
}
.logo, .auth-logo {
  background: linear-gradient(135deg, #7B44C4, #46216F);
  color: #fff;
}
#brandTitle { font-size: var(--t-lg); line-height: 1.25; }
.topbar .sub { font-size: var(--t-xs); }

/* Destination links: named, and reading as one row of equals.
   44px AND NOT 40. These sit in the top bar where a thumb reaches for them on
   a phone held one-handed, and 40 was the number that was already here — a
   size inherited rather than chosen. The rule is 44×44 for anything a finger
   is meant to hit, and a navigation link between three others is precisely
   where a near-miss lands on the wrong destination. */
.top-link {
  min-height: 44px; padding: 0 var(--s3);
  border-radius: var(--r-btn); color: var(--ink-2);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.top-link:hover { background: var(--accent-weak); color: var(--accent-press); }
.top-link .ic { opacity: .8; }

/* ===========================================================================
   CARDS — the console's one repeating object, so it is composed ONCE and
   every instance keeps the same edge, padding and title position. Border AND
   a resting shadow: the border does the work on a cheap monitor where a 4%
   shadow is invisible.
   =========================================================================== */
.section {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--e-rest);
  padding: var(--s5);
}
.section + .section { margin-top: var(--s4); }
.section > h2 { margin: 0 0 var(--s1); }
.section > h2 + .section-sub { margin: 0 0 var(--s4); }

/* THE INTRO CARD IS THE ONE THING ON THE PAGE ALLOWED TO BE LOUD, because it
   is the sentence that tells an owner why any of this matters. A brand wash
   and a leading rule — no shadow, so it reads as part of the page rather than
   as another thing to act on. */
.intro-card {
  background: linear-gradient(180deg, var(--accent-weak), var(--surface) 70%);
  border-color: var(--accent-weak-2);
  border-inline-start: 3px solid var(--accent);
  box-shadow: none;
}
.intro-body { font-size: var(--t-md); color: var(--ink-2); }
.steps { line-height: var(--lh-body); }

/* ===========================================================================
   STAT TILES — the figure leads and everything else gets out of its way.
   Deliberately NOT a card: no shadow, no white ground. A row of six white
   boxes on a white page is six things asking for attention; these are a
   readout.
   =========================================================================== */
.stat {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: none;
  padding: var(--s3) var(--s4);
}
.stat .stat-num {
  color: var(--accent-press);
  font-size: var(--t-2xl); font-weight: 700; line-height: 1.15;
}
.stat .stat-label { font-size: var(--t-xs); color: var(--muted); }

/* ===========================================================================
   NAVIGATION — two levels, and the selected one is never in doubt.
   =========================================================================== */
.pgroup {
  min-height: 48px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--ink-2); font-weight: 600;
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.pgroup:hover { color: var(--accent-press); border-color: var(--line-strong); background: var(--accent-weak); }
.pgroup.on,
.pgroup.on:hover {
  color: var(--on-accent); background: var(--accent); border-color: var(--accent);
  box-shadow: var(--e-rest);
}

/* The tab strip under it: a real 44px target, and the selected tab is marked
   by weight and colour as well as the rule — a 3px line alone is a colour-only
   signal, which is the one thing the accessibility rules refuse. */
.panel-tabs .ptab, .tab, .br-tab, .br-pill { min-height: 44px; }
.ptab { color: var(--muted); font-weight: 600; transition: color var(--dur-fast) var(--ease); }
.ptab:hover { color: var(--ink); }
.ptab.on { color: var(--accent-press); font-weight: 700; border-bottom-width: 3px; }

/* ===========================================================================
   CONTROLS
   =========================================================================== */
.primary {
  min-height: 44px; height: auto; padding: 10px var(--s5);
  border-radius: var(--r-pill); font-weight: 700; font-size: var(--t-md);
  background: var(--accent); color: var(--on-accent); border: 1px solid var(--accent);
  box-shadow: var(--e-rest);
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.primary:hover:not(:disabled) { background: var(--accent-hover); }
.primary:active:not(:disabled) { background: var(--accent-press); transform: translateY(1px); }
.primary:disabled { opacity: .5; box-shadow: none; }

.ghost, .btn-line, .btn-danger, .btn-approve {
  min-height: 44px; height: auto; padding: 8px var(--s4);
  border-radius: var(--r-btn); font-weight: 600;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.ghost:hover, .btn-line:hover { background: var(--accent-weak); border-color: var(--line-strong); }
.btn-danger { color: var(--danger); border-color: var(--line-strong); }
.btn-danger:hover { background: var(--danger-weak); border-color: var(--danger); }
/* APPROVE IS A FILLED BUTTON IN THIS CONSOLE, not an outline one — `owner.css`
   gives it the accent as a ground. Recolouring only its TEXT left green ink on
   a purple fill at 1.78:1, which is the failure mode of restyling a component
   by the class name rather than by what it actually renders as.
   It is filled GREEN rather than purple for a second reason: «احفظ التغييرات»
   and «اعتماد» sat side by side as two identical purple buttons, and a row
   with two primaries has no primary. `--on-accent` carries the ink because it
   is the token that already flips with the theme — white on the light-mode
   green, near-black on the lightened dark-mode one. */
.btn-approve {
  background: var(--ok); color: var(--on-accent); border-color: var(--ok);
}
.btn-approve:hover:not(:disabled) { filter: brightness(1.08); }
.btn-sm { min-height: 36px; height: auto; padding: 4px 12px; font-size: var(--t-sm); }
.icon-btn { width: 44px; height: 44px; border-radius: var(--r-btn); }

/* Fields: quiet until touched, and the label is always a label — never a
   placeholder standing in for one. */
.field > label { font-size: var(--t-sm); font-weight: 600; color: var(--ink-2); }
input, select, textarea {
  min-height: 44px; border-radius: var(--r-btn);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong);
  font-size: var(--t-md);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
input:hover, select:hover, textarea:hover { border-color: var(--muted); }
input:focus, select:focus, textarea:focus {
  border-color: var(--accent); box-shadow: var(--ring); outline: none;
}
input:disabled, select:disabled, textarea:disabled { background: var(--surface-2); color: var(--muted); }
textarea { min-height: 90px; line-height: var(--lh-body); }
input[type="checkbox"], input[type="radio"], input[type="color"],
input[type="file"], input[type="range"] { min-height: 0; }
.field .hint { font-size: var(--t-sm); color: var(--muted); line-height: 1.7; }

/* FOCUS IS ALWAYS VISIBLE — keyboard, or a gloved thumb on a till tablet. */
button:focus-visible, a:focus-visible, summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px;
}

/* ===========================================================================
   STATUS — A GROUND AND AN ICON, NEVER A COLOUR ALONE. Red-on-white and
   green-on-white are the same grey to a colour-blind reader and to a shop's
   sun-washed screen.
   =========================================================================== */
.ok-box, .error-box, .warn-box, .info-box {
  border-radius: var(--r-btn); padding: var(--s3) var(--s4);
  font-size: var(--t-sm); line-height: var(--lh-body);
  border: 1px solid transparent; border-inline-start-width: 3px;
}
.ok-box    { background: var(--ok-weak);     border-color: var(--ok);     color: var(--ok); }
.error-box { background: var(--danger-weak); border-color: var(--danger); color: var(--danger); }
.warn-box  { background: var(--warn-weak);   border-color: var(--warn);   color: var(--warn); }
.info-box  { background: var(--info-weak);   border-color: var(--info);   color: var(--info); }
.ok-box strong, .error-box strong, .warn-box strong, .info-box strong { font-weight: 700; }

.badge, .chip, .pill {
  border-radius: var(--r-chip); font-size: var(--t-xs); font-weight: 700;
  padding: 3px var(--s2);
  /* A LABEL DOES NOT WRAP. A two-word status chip breaking mid-phrase inside
     a table cell is how a row's height doubles and a list stops scanning. */
  white-space: nowrap;
}

/* ===========================================================================
   TABLES — a long member list has to be readable ACROSS, which is what
   striping is for, and it has to survive a phone, which is what the scroll
   wrapper is for.
   =========================================================================== */
table.data { font-size: var(--t-sm); }
table.data th {
  font-size: var(--t-xs); font-weight: 700; color: var(--muted);
  letter-spacing: .02em; background: var(--surface-2);
  position: sticky; top: 0; z-index: 1;
}
table.data tbody tr:nth-child(even) td { background: var(--surface-2); }
table.data tbody tr:hover td { background: var(--accent-weak); }
table.data td, table.data th { padding: var(--s2) var(--s3); }

/* A WIDE TABLE SCROLLS INSIDE ITS OWN BOX; the page never scrolls sideways.
   `-webkit-overflow-scrolling` keeps the momentum a phone expects. */
.table-wrap, .scroll-x {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border-radius: var(--r-card);
}

/* ===========================================================================
   EMPTY STATES — an empty list is an invitation, not a shrug. The dashed
   edge says «nothing here YET» in a way a solid card cannot.
   =========================================================================== */
.empty {
  border: 1px dashed var(--line-strong); border-radius: var(--r-card);
  background: var(--surface-2); padding: var(--s6) var(--s5);
  line-height: 1.9; color: var(--muted); text-align: center;
}
.empty strong { display: block; color: var(--ink); font-size: var(--t-lg); margin-bottom: var(--s1); }

/* ===========================================================================
   DISCLOSURE — the fold that keeps a first run to three decisions.
   =========================================================================== */
.lp-adv {
  border: 1px dashed var(--line-strong); border-radius: var(--r-card);
  background: var(--surface-2); margin-top: var(--s4);
}
.lp-adv > summary {
  display: flex; align-items: center; gap: var(--s2);
  min-height: 48px; padding: var(--s2) var(--s4);
  cursor: pointer; list-style: none;
  font-size: var(--t-sm); font-weight: 700; color: var(--muted);
}
.lp-adv > summary::-webkit-details-marker { display: none; }
.lp-adv > summary:hover { color: var(--ink); }
.lp-adv[open] { background: var(--surface); border-style: solid; border-color: var(--line); }
.lp-adv[open] > summary { color: var(--ink); }
.lp-adv > summary .ic { width: 18px; height: 18px; transition: transform var(--dur-move) var(--ease); }
.lp-adv[open] > summary .ic { transform: rotate(180deg); }
.lp-adv-b { padding: 0 var(--s4) var(--s4); }
.lp-adv .lp-row { margin-bottom: var(--s4); }
.lp-adv .lp-row:last-child { margin-bottom: 0; }
.lp-rows .lp-row {
  border-radius: var(--r-card); background: var(--surface);
  border: 1px solid var(--line);
}

/* ===========================================================================
   THE STICKY SAVE BAR — clearly a bar, never mistaken for one more card, and
   it floats because unsaved work is the one thing on the page that is above
   the page.
   =========================================================================== */
.ly-save .section {
  border-radius: var(--r-card) var(--r-card) 0 0;
  box-shadow: 0 -8px 28px rgba(31, 24, 48, .14);
  border-bottom: 0;
}
.ly-save .primary { min-width: 160px; }

/* ===========================================================================
   FOLDING A SECTION — the owner console is a column of a dozen cards and an
   owner comes to change one thing. The eleven they are not here for should be
   foldable, and the fold has to survive a reload or it is a toy.
   =========================================================================== */

/* THE HEADING IS STILL A HEADING; the button is inside it. So the h2 keeps its
   type and its place in the outline, and the button is just the hit area. */
.section > h2:has(.fold-t) { margin: 0; }
.fold-t {
  display: flex; align-items: center; gap: var(--s2); width: 100%;
  min-height: 44px; padding: 0; margin: 0;
  background: none; border: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: start;
  /* The whole width is the target — a heading a thumb has to hit exactly is a
     heading nobody folds twice. */
}
.fold-t:hover { color: var(--accent-press); }
.fold-ic {
  width: 18px; height: 18px; flex: 0 0 auto;
  margin-inline-start: auto; color: var(--muted);
  transition: transform var(--dur-move) var(--ease);
}
.fold-t[aria-expanded="false"] .fold-ic { transform: rotate(-90deg); }
/* IN ARABIC THE CHEVRON POINTS THE OTHER WAY when it is closed, because the
   content it would reveal opens toward the reading side. */
[dir="rtl"] .fold-t[aria-expanded="false"] .fold-ic { transform: rotate(90deg); }

/* A FOLDED CARD IS STILL A CARD, just a shorter one: the padding closes up so
   a column of folded sections reads as a list of titles rather than as a
   column of empty boxes. */
.section.folded { padding-block: var(--s3); }
.section.folded > h2 + .fold-body { display: none; }

/* ===========================================================================
   DENSITY — a dashboard is scanned, not read. This comes in ONLY on wide
   screens: a phone keeps the roomier rhythm, because a thumb needs the space
   a mouse does not. Nothing here touches a 44px minimum.
   =========================================================================== */
@media (min-width: 1024px) {
  .section { padding: var(--s4) var(--s5); }
  .section + .section { margin-top: var(--s3); }
  table.data td, table.data th { padding: 6px var(--s3); }
  .stat { padding: var(--s2) var(--s3); }
}

/* THE WIDE LAYOUT. Beyond ~1200px a single column of full-width cards makes
   an owner's eye travel the whole monitor for one field, so the reading
   measure is capped and the page centres. */
main.wrap { max-width: 1180px; margin-inline: auto; }

/* ===========================================================================
   THE PHONE. An owner does most of this standing in their own shop, so the
   phone is not the degraded case — it is the common one.
   =========================================================================== */
@media (max-width: 640px) {
  /* Cards lose their side inset: on a 390px screen, 24px of padding either
     side spends an eighth of the width on nothing. */
  .section { padding: var(--s4) var(--s3); border-radius: var(--r-btn); }
  main.wrap { padding-inline: var(--s2); }

  /* THE THREE-UP GROUP BAR STACKS ITS LABEL UNDER ITS ICON rather than
     shrinking the type: three Arabic words side by side at 390px either wrap
     mid-word or drop below the 12px floor, and both are worse than two lines. */
  .pgroup { flex-direction: column; gap: 4px; min-height: 60px; font-size: var(--t-sm); }

  /* A TABLE BECOMES A LIST. Five columns of member data do not fit any phone,
     and a horizontal scroll inside a vertical scroll is a gesture nobody wins:
     each row stacks, each cell carries its own header from `data-label`, and
     the head is hidden. Rows the console draws without labels keep the
     scroller above — this only applies where the markup can support it. */
  table.data.stacked thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  table.data.stacked tbody tr {
    display: block; padding: var(--s2) 0;
    border-bottom: 1px solid var(--line);
  }
  table.data.stacked tbody td {
    display: flex; justify-content: space-between; gap: var(--s3);
    padding: 3px 0; border: 0;
  }
  table.data.stacked tbody td::before {
    content: attr(data-label); color: var(--muted); font-size: var(--t-xs); font-weight: 700;
  }

  /* Buttons in a row go full width rather than wrapping into a ragged stack. */
  .section > .row-actions .primary, .section > .row-actions .ghost { flex: 1 1 auto; }

  /* The stat strip scrolls sideways INSIDE ITSELF instead of squeezing four
     figures into 390px — a number too small to read is not a number. */
  .stat-strip { display: flex; gap: var(--s2); overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .stat-strip > .stat { flex: 0 0 46%; }
}

/* ===========================================================================
   MOTION — respected, not decorated. A reduced-motion request is a medical
   setting for some readers, so it turns off transitions rather than shortening
   them, and every animated state has a resting equivalent.
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important; animation: none !important;
    scroll-behavior: auto !important;
  }
}

/* PRINT — an owner printing a member list or a settlement wants the data, not
   the chrome. Nothing here is decorative enough to survive a printer. */
@media print {
  .topbar, .pgroup-bar, .panel-tabs, .ly-save, .top-nav { display: none !important; }
  .section { box-shadow: none; border-color: #000; break-inside: avoid; }
  body { background: #fff; }
}
