/* ==========================================================================
   THE BOOKING WIZARD — `حجز جديد`
   docs/design/WIZARD_SPEC.md + the twelve Wizard*/MobileWizard* artboards
   (package Issue 12). Loaded by templates/base.html, because the wizard
   opens over EVERY screen and the host div lives in the shell.

   THIS FILE IS THE SHELL ONLY — the scrim, the frame, the panel, the step
   header and the body's two columns. Each step's own vocabulary is below
   it, in its own section, so three people can work on three steps without
   meeting in the same rules.

   RULES THIS FILE IS HELD TO (docs/DESIGN_SYSTEM.md §1, and they are tests,
   not preferences): logical properties only — never left/right; every
   colour from a token; no shadows; no italics.
   ========================================================================== */

/* The wizard's own root. It carries no layout -- the scrim and the frame
   below are both `position: fixed` and escape it -- but it is the element
   the Alpine component and the Escape handler are bound to, and a class a
   template uses must exist in a stylesheet (there is a test). */
.wiz { display: contents; }

/* THE SCRIM COVERS THE WHOLE PAGE; THE PANEL COVERS THE CONTENT COLUMN.
   Those are two different boxes on purpose (WIZARD_SPEC §0: "centred over
   the content column, never over the sidebar", "scrim at 38%"). A single
   box doing both would either dim nothing behind the sidebar or centre the
   panel over the whole viewport. */
.wiz__scrim {
  position: fixed;
  inset: 0;
  z-index: 80;
  /* The artboard's own rgba(12,18,14,.38). A token would have to be a
     fourth near-black; this is the only scrim in the product that is not
     already `--scrim`, and it is declared here rather than added to the
     palette for one user. */
  background: rgba(12, 18, 14, 0.38);
  border: 0;
  cursor: pointer;
}

.wiz__frame {
  position: fixed;
  /* THE CONTENT COLUMN, not the page: the artboard positions the frame at
     `inset-inline-start: 248px` — the sidebar's width — and the panel
     centres inside what is left. `var(--sidebar-width)` rather than the
     literal, so the collapsed 72px rail moves the modal with it. */
  inset-inline-start: var(--sidebar-width);
  inset-inline-end: 0;
  /* 84px in the artboard: the 56px top bar plus 28px of air. */
  inset-block-start: 84px;
  inset-block-end: 0;
  display: flex;
  justify-content: center;
  /* Above the shell's own overlays (the palette is 70) and far above the
     sidebar's collapse handle, which package Issue 12 lowered to 1 for
     exactly this reason — the handle sits half outside the sidebar, in the
     same pixels as this panel's edge. */
  z-index: 90;
  pointer-events: none;
  overflow-y: auto;
}
.app--rail .wiz__frame { inset-inline-start: var(--sidebar-rail-width); }

.wiz__panel {
  pointer-events: auto;
  inline-size: 1024px;
  max-inline-size: 100%;
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* NO BOX-SHADOW, against the artboard's `0 28px 70px rgba(12,22,15,.30)`.
     DESIGN_SYSTEM §1 says no shadows anywhere, and the standing tiebreak
     for a popover — already applied to the account menu and the calendar's
     own popovers — is that §1 wins. Recorded in docs/LIKENESS.md. */
}

/* ---- the header: close · the three steps · the counter ------------------ */

.wiz__head {
  display: flex;
  align-items: center;
  gap: var(--sp-14);
  padding: var(--sp-14) var(--sp-18);
  border-block-end: 1px solid var(--line);
}

.wiz__close {
  inline-size: 32px;
  block-size: 32px;
  flex: none;
  border-radius: 9px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted-2);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.wiz__close:hover { border-color: var(--muted-2); }

.wiz__steps {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-12);
}

.wiz__step {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  font-size: var(--fs-13);
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
}
.wiz__step--on { font-weight: 700; color: var(--ink); }
/* A DONE STEP STAYS MUTED, which the build got wrong by colouring it
   `--ink` -- making a finished step look as prominent as the one you are
   on. The artboard draws it 13px/600 in #5F6A61 (`--muted-2`): behind you,
   legible, not competing. Caught by the dimensional pass. */
.wiz__step--done { color: var(--muted-2); }

.wiz__step-mark {
  inline-size: 26px;
  block-size: 26px;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--chip);
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12.5px;
  font-weight: 600;
}
.wiz__step--on .wiz__step-mark {
  background: var(--primary);
  color: var(--on-primary);
  font-weight: 700;
}
/* Done is a GREEN CHECK (§0) in a SOFT BRAND well with a border -- the
   artboard's `#E9F0EC` fill, `#CFE0D4` border, `#1B5E34` tick. A finished
   step and the step you are on must not look the same at a glance, and a
   plain success chip was not what the drawing shows.

   `--success-border` (#D2E6D5) stands in for the drawn #CFE0D4: three
   units apart on one channel, and the alternative is a token whose only
   user is this one border. */
.wiz__step--done .wiz__step-mark {
  background: var(--primary-soft);
  border: 1px solid var(--success-border);
  color: var(--weekend-text);
  /* 28, NOT 26. The artboard draws a 26px circle with a 1px border and has
     no `box-sizing` reset, so its OUTER size is 28 -- while this product
     is `border-box` everywhere, which would have made the bordered done
     mark 2px smaller than the unbordered active one beside it. The step
     row's own height followed it: 26 against a drawn 28, on three
     artboards. */
  inline-size: 28px;
  block-size: 28px;
}

.wiz__joint {
  inline-size: 56px;
  block-size: 2px;
  flex: none;
  border-radius: 2px;
  background: var(--border);
}
.wiz__joint--on { background: var(--primary); }

.wiz__counter {
  min-inline-size: 32px;
  display: flex;
  justify-content: flex-end;
  font-size: var(--fs-11);
  color: var(--muted);
  white-space: nowrap;
}

/* ---- the sheet header's own parts -------------------------------------
   Drawn by `MobileWizard.dc.html` and INERT ON A DESKTOP: the grab handle,
   the 17px name, the unit/option parts of the sub-line and the guest name
   are all `display: none` here, so the desktop header is exactly the close
   target, the three pips and the counter it has always been. The §8 block
   below reveals them. */
.wiz__grab,
.wiz__title-name,
.wiz__title-part,
.wiz__head-guest { display: none; }

/* The wrapper the counter now lives in. On a desktop it has to behave as
   the counter did on its own -- pushed to the inline-end of the header --
   because `.wiz__steps` takes `flex: 1` and this is what follows it. */
.wiz__title { margin-inline-start: auto; min-inline-size: 0; }

/* ---- the body: the step, then the live summary column ------------------- */

.wiz__body {
  display: flex;
  min-block-size: 480px;
}

.wiz__content {
  flex: 1;
  min-inline-size: 0;
  padding: var(--sp-20) var(--sp-22);
}

/* The success body has no summary column beside it, so it is one box. */
.wiz__body--done { display: block; }

/* ==========================================================================
   §8 — THE PHONE (MobileWizard.dc.html)

   A FULL SHEET, not a shrunken modal: the panel fills the viewport, the
   frame loses its sidebar inset, and the two body columns become one. The
   spec's own targets are 44/48px and `core/test_design_rules.py` checks
   the 44 on phone controls.
   ========================================================================== */

@media (max-width: 639px) {
  .wiz__frame {
    inset-inline-start: 0;
    inset-block-start: 0;
  }

  /* THE SHEET IS A THREE-PART COLUMN: a header that does not move, a body
     that scrolls, and a footer pinned to the bottom edge. Every one of the
     three declarations below is load-bearing and the absence of them is
     the defect the owner found on his own phone.

     `block-size: 100%` and NOT `min-block-size`: the frame is
     `position: fixed; inset: 0`, so 100% of it IS the viewport. With
     `min-` the panel grew to its content's height instead -- and since
     `.wiz__panel` carries `overflow: hidden` (it clips the desktop panel's
     radius), everything past the first screenful was PAINTED AND
     UNREACHABLE: no scrollbar, no overscroll, nothing a thumb could do.
     The wizard's primary action is the last thing in the column, so what
     was unreachable was «التالي» and «تأكيد الحجز» -- the whole point of
     the screen. Measured at 390x780: the panel was 1826px tall inside a
     780px box with `overflow-y: hidden` and no scroller anywhere.

     `min-block-size: 0` on the body is the flexbox half of it. A flex item
     will not shrink below its content without it, so `overflow-y: auto`
     would have had nothing to scroll. */
  .wiz__panel {
    inline-size: 100%;
    block-size: 100%;
    max-block-size: 100%;
    border: 0;
    border-radius: 0;
    align-self: stretch;
  }
  .wiz__head {
    flex: none;
    flex-wrap: wrap;
    gap: var(--sp-10);
    padding: var(--sp-12) var(--sp-14);
    /* The sheet's own ground, so the header never shows page behind it. */
    background: var(--surface);
  }

  /* MobileWizard's drag indicator: a 36x4 pill, centred, above everything
     else in the header. `order: -1` with a full-width basis puts it on its
     own line without a wrapper element. */
  .wiz__grab {
    display: block;
    order: -1;
    flex-basis: 100%;
    inline-size: 36px;
    block-size: 4px;
    margin: 0 auto var(--sp-6);
    border-radius: var(--radius-pill);
    background: var(--border);
  }

  /* THE PIPS GO ENTIRELY, which is a change from this block's first issue:
     it kept the marks and connectors and hid only the words. The artboard
     draws neither -- it draws a title and a counted sub-line -- and three
     28px circles plus two connectors is 140px of a 360px bar that says
     exactly what «خطوة 2 من 3» says in a quarter of the room. */
  .wiz__steps { display: none; }

  .wiz__close {
    inline-size: var(--nav-item-height);
    block-size: var(--nav-item-height);
    order: 1;
  }

  .wiz__title {
    order: 2;
    flex: 1;
    min-inline-size: 0;
    margin-inline-start: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    line-height: 1.3;
  }
  .wiz__title-name {
    display: block;
    font-size: 17px;
    font-weight: 700;
    color: var(--ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* The sub-line is one 11px row that ELLIPSISES rather than wrapping the
     header to three lines -- the same treatment the shell's phone bar
     gives its own sub-line, for the same reason. Its parts are inline so
     the whole line truncates as one string.

     `display: block` AND NOT `flex`, and the difference is visible: a flex
     container makes every child a flex ITEM, and the leading whitespace
     inside an item is trimmed. The separators are written « · » with a
     space on each side, and as flex items they rendered «النخيل· الفترة»
     -- the space before each dot eaten, the one after it kept. Inline
     children keep their own spaces, which is all this line needs. */
  .wiz__title-sub {
    display: block;
    min-inline-size: 0;
    font-size: 11px;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .wiz__title-part { display: inline; }
  .wiz__counter {
    display: inline;
    min-inline-size: 0;
    font-size: 11px;
    flex: none;
  }

  .wiz__head-guest {
    display: block;
    order: 3;
    flex: none;
    max-inline-size: 38%;
    font-size: 12px;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* ---- the scrolling body -------------------------------------------- */
  .wiz__body {
    display: block;
    flex: 1 1 auto;
    min-block-size: 0;
    overflow-y: auto;
    /* A sheet that scrolls its own body must not also scroll the page
       behind it when it reaches the end. */
    overscroll-behavior: contain;
  }
  .wiz__content { padding: var(--sp-14) var(--sp-14) 0; }

  /* THE ASIDE AND ITS FOOTER ARE NOT HERE. They are in this file's LAST
     phone block, and they have to be: `.wiz__aside`, `.wiz__aside-footer`,
     `.wiz__aside-due` and `.wiz__aside-btn` are all defined ~1,400 lines
     BELOW this point, and `@media` adds no specificity -- so a phone rule
     written here loses to the base rule written later. It did: the footer's
     `display: grid` was overruled by the base `display: flex;
     flex-direction: column`, and the two buttons stacked instead of sharing
     a row. The symptom was a correct-looking stylesheet and a wrong screen.
     (`backoffice.css` carries the same lesson at its own foot, with the
     test that guards it.) */

  /* THE STEP CONTROLS' TOUCH TARGETS ARE NOT HERE EITHER, and for the third
     time in this file the reason is the cascade: `.wiz-month-nav`,
     `.wiz-guest-search`, `.wiz-guest-new-btn` and
     `.wiz-guest-chosen__clear` are all defined BELOW this block, so a rule
     written here loses to its own base. It did -- the month picker's
     prev/next buttons measured 32x32 at 390px with a 44px rule sitting
     right here, inert. They live in the file's last phone block with the
     aside's. */
}


/* ==========================================================================
   STEP 1 — الاختيار  (WizardChoose.dc.html)
   ========================================================================== */

/* Booking wizard — Step 1 (الاختيار). Source: docs/design/artboards/WizardChoose.dc.html
   and docs/design/WIZARD_SPEC.md §1. Every class here is prefixed `wiz-`
   (single dash) so it cannot collide with the shell's `.wiz__*` (BEM, double
   underscore) classes written for `_modal.html` — this file does not touch
   those and does not redefine them.

   CROSS-STEP NOTE for whoever merges the per-step files: `.wiz-step` itself
   is shared by every step's root element (the Alpine contract requires that
   literal class name on all three), and step 2's own file already gives it
   `display: flex` for its two-column body. Step 1 has no second column and
   needs its content to stack block-wise, so this file does NOT touch the
   bare `.wiz-step` rule (merge order should not decide step 1's layout) —
   it adds a second class, `.wiz-choose`, on the same root element and
   overrides display through the compound selector `.wiz-step.wiz-choose`,
   whose two-class specificity wins over the single-class `.wiz-step` rule
   regardless of which file the merged stylesheet loads first.

   Artboard values copied verbatim where the artboard draws the element
   (unit row, price cards, the guest row's three doors, the skip-consequence
   line) — including font sizes off the formal 11/12/13/14/15… scale
   (11.5px, 12.5px, 13.5px), which is this codebase's own established
   practice (base.css, calendar.css already ship 10.5–14.5px literals) and
   the artboard's border-radius 13px on the price card, which has no
   matching token (the nearest is --radius-lg at 12px) and is kept literal
   rather than rounded, per the artboard's own authority over values.
   The guest-chosen / guest-skipped / search-results states are NOT drawn
   by this artboard (it only draws the undecided default); their values are
   this file's own, built from the token scale rather than copied, since
   there was nothing to copy. Every colour below is a token — none hard-coded.
*/

.wiz-step.wiz-choose {
  display: block;
}

/* ---- the unit picker ----------------------------------------------------
   Owner finding 3: a grid of cards, not a <select>. The card itself is
   `.wiz-card`/`.wiz-card__*` — the SAME classes `_options.html` draws the
   price cards with, reused rather than duplicated, so "selected" means one
   thing in this step. Only the grid wrapper is new, and it resets the
   price card's own `margin-block-end` (meant for a vertical stack) since
   the grid's `gap` already spaces two columns in both directions. */

.wiz-unit-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-10);
  margin-block-end: var(--sp-16);
}

.wiz-unit-card {
  margin-block-end: 0;
}

@media (max-width: 639px) {
  .wiz-unit-grid {
    grid-template-columns: 1fr;
  }
}

/* ---- section titles ("خيارات السعر" / "الضيف") -------------------------- */

.wiz-section-title {
  font-size: var(--fs-14);
  font-weight: 700;
  color: var(--ink);
  margin-block-end: var(--sp-10);
}
.wiz-section-title--guest {
  margin-block-start: var(--sp-16);
}

/* ---- the price cards ----------------------------------------------------
   Artboard: border #E8E7E3/13px radius/14px 16px padding; selected card
   1.5px #27462E border + #E9F0EC fill + a filled check circle. */

.wiz-card {
  display: flex;
  align-items: center;
  gap: var(--sp-12);
  width: 100%;
  margin-block-end: var(--sp-10);
  padding: var(--sp-14) var(--sp-16);
  border: 1px solid var(--border);
  border-radius: 13px;
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  text-align: start;
  cursor: pointer;
}
.wiz-card--on {
  border: 1.5px solid var(--primary);
  background: var(--primary-soft);
}

.wiz-card__radio {
  flex-shrink: 0;
  inline-size: 20px;
  block-size: 20px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
}
.wiz-card__radio--on {
  border-color: transparent;
  background: var(--primary);
  color: var(--on-primary);
}

.wiz-card__body {
  flex: 1;
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.5;
}
.wiz-card__label {
  font-size: 13.5px;
  font-weight: 700;
}
.wiz-card__time {
  font-size: 11.5px;
  color: var(--muted);
}

.wiz-card__price {
  flex-shrink: 0;
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
}
.wiz-card__currency {
  font-size: var(--fs-11);
  font-weight: 400;
  color: var(--muted);
}
.wiz-card__price--empty {
  font-size: 12.5px;
  font-weight: 400;
  color: var(--muted);
}

/* ---- the guest row: search / + ضيف جديد / تخطّي الآن --------------------- */

.wiz-guest-row {
  display: flex;
  align-items: center;
  gap: var(--sp-10);
  flex-wrap: wrap;
}

.wiz-guest-search {
  flex: 1;
  min-inline-size: 160px;
  block-size: 40px;
  display: flex;
  align-items: center;
  gap: 9px;
  padding-inline: var(--sp-12);
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
}
.wiz-guest-search__input {
  flex: 1;
  min-inline-size: 0;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--ink);
}
.wiz-guest-search__input::placeholder {
  color: var(--muted);
}

.wiz-guest-new-btn {
  block-size: 40px;
  display: flex;
  align-items: center;
  gap: 7px;
  padding-inline: 14px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted-2);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

.wiz-guest-skip {
  border: 0;
  background: none;
  padding: 0;
  color: var(--primary);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

.wiz-guest-hint {
  margin-block-start: var(--sp-8);
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--muted);
}

/* ---- search results (#wiz-guest-results's "results"/empty states) ------
   Not drawn by this artboard — built from the token scale. */

.wiz-results {
  margin-block-start: var(--sp-8);
  max-block-size: 220px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
}
.wiz-result-row {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--sp-10);
  padding: var(--sp-10) var(--sp-12);
  border: 0;
  border-block-end: 1px solid var(--line);
  background: var(--surface);
  font-family: inherit;
  text-align: start;
  cursor: pointer;
}
.wiz-result-row:last-child {
  border-block-end: 0;
}
.wiz-result-row:hover {
  background: var(--chip);
}
.wiz-result-row__avatar {
  flex-shrink: 0;
  inline-size: 28px;
  block-size: 28px;
  border-radius: var(--radius-pill);
  background: var(--avatar-bg);
  color: var(--avatar-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
}
.wiz-result-row__text {
  flex: 1;
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.4;
}
.wiz-result-row__name {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wiz-result-row__phone {
  font-size: 11px;
  color: var(--muted);
}
.wiz-results__empty {
  margin-block-start: var(--sp-8);
  padding: var(--sp-10) var(--sp-12);
  border-radius: var(--radius-sm);
  background: var(--chip);
  color: var(--muted);
  font-size: 12.5px;
}

/* ---- the inline new-guest form ------------------------------------------
   Not drawn by this artboard — built from the token scale. */

.wiz-newguest {
  margin-block-start: var(--sp-8);
  display: flex;
  flex-direction: column;
  gap: var(--sp-10);
  padding: var(--sp-14);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.wiz-newguest__back {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  border: 0;
  background: none;
  padding: 0;
  color: var(--muted-2);
  font-size: var(--fs-12);
  font-weight: 600;
  cursor: pointer;
}
.wiz-newguest__errors {
  margin: 0;
  padding-inline-start: var(--sp-16);
  color: var(--danger-text);
  font-size: var(--fs-12);
}
.wiz-newguest__submit {
  block-size: 40px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--primary);
  color: var(--on-primary);
  font-size: var(--fs-13);
  font-weight: 700;
  cursor: pointer;
}
.wiz-newguest__submit:hover {
  background: var(--primary-hover);
}

.wiz-form-row {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.wiz-form-label {
  font-size: var(--fs-12);
  font-weight: 600;
  color: var(--muted-2);
}
.wiz-form-input {
  block-size: 40px;
  padding-inline: var(--sp-12);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-13);
}

/* ---- the chosen-guest card -----------------------------------------------
   Styled after the artboard's OWN right-column guest card (avatar in
   --primary-soft/--primary, 36px pill) for visual continuity, even though
   that card belongs to `_summary.html`, not this file — reusing its exact
   avatar treatment here is a deliberate echo, not a token invented fresh. */

.wiz-guest-chosen-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
}
.wiz-guest-chosen {
  display: flex;
  align-items: center;
  gap: var(--sp-10);
  padding: var(--sp-12) var(--sp-14);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.wiz-guest-chosen__avatar {
  flex-shrink: 0;
  inline-size: 36px;
  block-size: 36px;
  border-radius: var(--radius-pill);
  background: var(--primary-soft);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
}
.wiz-guest-chosen__text {
  flex: 1;
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.4;
}
.wiz-guest-chosen__name {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}
.wiz-guest-chosen__phone {
  font-size: 11px;
  color: var(--muted);
}
.wiz-guest-chosen__clear {
  flex-shrink: 0;
  inline-size: 28px;
  block-size: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--faint);
  cursor: pointer;
}
.wiz-guest-chosen__clear:hover {
  color: var(--muted-2);
}
.wiz-guest-chosen__reused {
  margin: 0;
  font-size: 11.5px;
  color: var(--muted);
}

/* ---- the skipped-guest note -----------------------------------------------
   Dashed neutral treatment, matching the calendar's own "محجوب" (blocked)
   vocabulary (--neutral-bg/--neutral-border/--neutral-text) rather than a
   fresh colour for the same idea of "deliberately set aside". */

.wiz-guest-skipped {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-10);
  padding: var(--sp-12) var(--sp-14);
  border: 1px dashed var(--neutral-border);
  border-radius: var(--radius-lg);
  background: var(--neutral-bg);
  color: var(--neutral-text);
}
.wiz-guest-skipped__text {
  flex: 1;
  min-inline-size: 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--neutral-text);
}
.wiz-guest-skipped__undo {
  flex-shrink: 0;
  border: 0;
  background: none;
  padding: 0;
  color: var(--primary);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}


/* ==========================================================================
   STEP 2 — الموعد  (WizardDate.dc.html)
   ========================================================================== */

/* Booking wizard — Step 2 (الموعد). Source: docs/design/artboards/WizardDate.dc.html
   and docs/design/WIZARD_SPEC.md §2. Every class here is prefixed `wiz-`
   (single dash) so it cannot collide with the shell's `.wiz__*` (BEM, double
   underscore) classes written for `_modal.html` — this file does not touch
   those and does not redefine them.

   Token discrepancies found against the artboard's own hex values, kept here
   as a permanent note (also in the build report):
     - The artboard's "past day" / legend swatch grey is #C3C8C3. tokens.css's
       own `--chevron` is #8A908A (a DIFFERENT colour), so that name was
       wrong on sight. The EXACT hex match is `--free-dash` (#C3C8C3), but its
       documented role is "MobileCalendar: the free-unit card's dashes" --
       FREE/available, the opposite of what a past day means. A token saying
       the opposite of the pixel is worse than one that's a few units off, so
       used `--faint` instead (#8B8F8B light / #5A645C dark) -- its own
       documented role is "adjacent-month day numbers", which is exactly this
       job: a de-emphasised, non-interactive date number. Not an exact colour
       match; a correct one.
     - The artboard's selected-day / primary-button text is #FCFFFD in a few
       places (e.g. the calendar's selected cell). tokens.css's `--on-primary`
       is #FDFDFD — one unit off in two channels. Used `--on-primary`: it is
       the token FOR this exact role ("text on the PRIMARY FILL only") and the
       artboard's figure reads as a rendering artefact, not a second token. */

/* ---- step root: two columns, matching the artboard's body row ---- */
.wiz-step {
  display: flex;
  width: 100%;
  min-width: 0;
}

.wiz-date-main {
  flex: 1;
  min-width: 0;
  padding: 20px 22px;
}

.wiz-date-side {
  width: 300px;
  flex-shrink: 0;
  border-inline-start: 1px solid var(--line);
  background: var(--surface-2);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* ---- month grid header ---- */
.wiz-month-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-block-end: 14px;
}

.wiz-month-nav {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted-2);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
}

/* "Previous month" points the other way, and it does so through the
   INHERITED MULTIPLIER rather than a direct transform on the <svg>.

   IT WAS `transform: scaleX(-1)` AND THAT IS THE EXACT MISTAKE base.css's
   `.icon--directional` block warns about, five lines of comment devoted to
   it: "Two transforms on one element do not compose -- the more specific
   wins". `chevron` became a directional glyph, so every one of them already
   carries `transform: scaleX(var(--icon-dir))`, which is -1 in Arabic. The
   prev button's own rule then set -1 as well, and -1 is not -1 twice: it is
   -1. **In Arabic both month arrows pointed the same way**, measured at
   390px — `matrix(-1, 0, 0, 1, 0, 0)` on both — so the picker offered two
   identical buttons and the reader had to learn which was which by pressing
   one. In English it was correct, which is why it survived.

   The idiom is `.tl-nav__btn--flip`'s, copied rather than reinvented: set
   the multiplier for this subtree, and set it the other way in RTL, because
   in RTL the glyph is already flipped and flipping again returns it. */
.wiz-month-nav--prev { --icon-dir: -1; }
[dir="rtl"] .wiz-month-nav--prev { --icon-dir: 1; }

.wiz-month-title {
  flex: 1;
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
}

/* ---- weekday header + day grid ---- */
.wiz-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  margin-block-end: 6px;
}

.wiz-weekday {
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
}

.wiz-days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}

.wiz-day {
  position: relative;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: none;
  color: var(--ink);
  font-family: inherit;
  font-size: 13.5px;
  font-variant-numeric: tabular-nums;
  padding: 0;
  cursor: pointer;
}

/* Excludes the selected/range states explicitly, not just by relying on
   source order: `:not(:disabled):hover` already carries three selectors'
   worth of specificity (a class plus two pseudo-classes), which otherwise
   beats a single-class rule like `.wiz-day--range-end` regardless of which
   is written later in the file -- confirmed live, hovering the range's end
   cell painted the plain hover tint straight over the primary fill. */
.wiz-day:not(:disabled):not(.wiz-day--selected):not(.wiz-day--in-range):not(.wiz-day--range-end):hover {
  background: var(--row);
}

.wiz-day:disabled {
  cursor: not-allowed;
}

/* FINDING 2 -- owner REVERSAL of his own earlier ruling, 11 Oct 2026:
   WIZARD_SPEC §2 and the WizardDate artboard draw `booked` as a full red
   fill. The owner reversed that -- a booked day now reads exactly like an
   ordinary cell, plus the small `.wiz-day__dot` mark below, and stays
   `disabled` so it cannot be picked. Do NOT restore the artboard's fill. */
.wiz-day--booked {
  background: none;
  border-color: var(--line);
  color: var(--ink);
  font-weight: 400;
}

/* The dot itself. `--badge-urgent` on the panel's own ground (`--surface`)
   measures 4.83:1 light / 3.76:1 dark -- both clear the 3:1 graphics
   threshold (WCAG 1.4.11); it is a fill, not a foreground token, so it is
   already exempt from the usage map (core/test_design_rules.py). Centred
   with `inset-inline: 0` + `margin-inline: auto` -- auto margins split the
   leftover space on whichever physical side is actually left/right, so it
   centres correctly in both directions. `inset-inline-start: 50%` plus
   `translateX(-50%)` (the usual LTR trick) does NOT: the 50% anchor is the
   dot's own inline-start edge, which is its RIGHT edge under RTL, and
   translateX always shifts by physical pixels -- the two flips compound
   instead of cancelling, landing the dot a whole dot-width off centre. */
.wiz-day__dot {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 7px;
  margin-inline: auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--badge-urgent);
}

.wiz-day--past {
  background: none;
  border-color: transparent;
  color: var(--faint);
}

/* Today is OUTLINED, never filled. */
.wiz-day--today {
  border: 1.5px solid var(--primary);
  color: var(--ink);
  font-weight: 700;
}

/* ---- range selection (owner finding 1) ----
   The start, the end and every day strictly between them share one fill so
   a multi-night stay reads as a band, not as separate chips. `--selected`
   also carries a LONE start with no `end` yet (still picking) -- it alone
   keeps the cell's ordinary all-round radius. The moment `end` exists,
   `--range-start`/`--in-range`/`--range-end` take over the corners and
   bleed each cell half the grid's own 6px gap (`.wiz-days`' `gap`) into the
   gutter on the side facing the rest of the range, so adjacent fills touch
   with no seam. This only connects within one row -- a range that wraps a
   week boundary reads as one band per row, which the finding did not ask
   this grid to solve. */
.wiz-day--selected,
.wiz-day--in-range,
.wiz-day--range-end {
  background: var(--primary);
  border-color: transparent;
  color: var(--on-primary);
  font-weight: 700;
}

.wiz-day--range-start {
  border-start-end-radius: 0;
  border-end-end-radius: 0;
  margin-inline-end: -3px;
}

.wiz-day--range-end {
  border-start-start-radius: 0;
  border-end-start-radius: 0;
  margin-inline-start: -3px;
}

.wiz-day--in-range {
  border-radius: 0;
  margin-inline: -3px;
}

/* ---- legend ---- */
.wiz-legend {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-block-start: 12px;
  font-size: 11.5px;
  color: var(--muted);
}

.wiz-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
}

.wiz-legend-swatch {
  position: relative;
  width: 10px;
  height: 10px;
  border-radius: 3px;
}

/* FINDING 2 -- owner REVERSAL, 11 Oct 2026: the legend's booked swatch must
   match the cell it describes -- a small red dot on a plain tile, not a
   filled square. See `.wiz-day--booked`/`.wiz-day__dot` above for the same
   treatment at cell size. */
.wiz-legend-swatch--booked {
  background: none;
  border: 1px solid var(--line);
}
.wiz-legend-swatch--booked::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 2px;
  margin-inline: auto;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--badge-urgent);
}
.wiz-legend-swatch--past { background: var(--faint); }

/* ---- side panel fields ---- */
.wiz-field {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 9px 12px;
}

.wiz-field-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.wiz-field-pair {
  display: flex;
  gap: 8px;
}

.wiz-field-flex {
  flex: 1;
  min-width: 0;
}

.wiz-field-label {
  font-size: 11.5px;
  color: var(--muted);
}

.wiz-field-value {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}

.wiz-field-value-md {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
}

/* The editable unit-price / guest-count inputs sit INSIDE a `.wiz-field-row`
   as its value side -- no border/background of their own, so a field with an
   empty input reads exactly like the artboard's static value, not like a
   lesser input nested inside a card. */
.wiz-price-input,
.wiz-count-input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
  text-align: end;
}

.wiz-price-input::placeholder,
.wiz-count-input::placeholder {
  color: var(--muted);
  font-weight: 400;
}

.wiz-price-input:focus,
.wiz-count-input:focus {
  outline: none;
}

.wiz-price-hint {
  font-size: 10.5px;
  color: var(--muted);
  margin-block-start: 3px;
}

.wiz-note {
  width: 100%;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 9px 12px;
  font-family: inherit;
  font-size: 11.5px;
  color: var(--ink);
  resize: none;
}

.wiz-note::placeholder {
  color: var(--muted);
}

.wiz-note:focus {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* ---- footer: amount due + the two navigation controls ---- */
.wiz-side-footer {
  margin-block-start: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.wiz-due {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
}

.wiz-btn-next {
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius);
  background: var(--primary);
  color: var(--on-primary);
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  width: 100%;
}

.wiz-btn-prev {
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--muted-2);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  width: 100%;
}


/* ==========================================================================
   STEP 3, THE SUMMARY COLUMN AND SUCCESS
   (WizardPay / WizardPayBank / WizardDone)
   ========================================================================== */

/* ==========================================================================
   WIZARD STEP 3 — الدفع — THE SUMMARY COLUMN — SUCCESS
   Source: docs/design/artboards/WizardPay.dc.html (cash),
           docs/design/artboards/WizardPayBank.dc.html (bank transfer),
           docs/design/artboards/WizardDone.dc.html (success).
   Templates: reservations/templates/reservations/wizard/
     _step_pay.html, _pay.html, _summary.html, _done.html.

   NAMING: every class here is `wiz-`-prefixed, except `.wiz__aside` and its
   `.wiz__aside-*` children — the brief's own named exception, since the
   summary column lives in the shell's own BEM family (wizard.css owns
   `.wiz__scrim`/`.wiz__frame`/`.wiz__panel`/`.wiz__head`/`.wiz__body`, but
   NOT the aside, which this file draws in full).

   TOKENS ONLY — no literal colour anywhere below; static/css/tokens.css is
   the one place a hex may appear (core/test_design_rules.py). Logical
   properties only (margin-inline-*, border-*-start/end, text-align start/
   end) — never left/right. No shadows, no italics, no type="number".
   ========================================================================== */

/* --------------------------------------------------------------------------
   STEP 3 BODY — the method cards, the discount input, the amount panel
   -------------------------------------------------------------------------- */

.wiz-step {
  display: block;
}

.wiz-pay-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-10);
}

.wiz-pay-card {
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 13px;
  padding: var(--sp-16);
  display: flex;
  flex-direction: column;
  align-items: center;
  /* 7px, the artboard's own figure -- not --sp-8. The scale has no 7,
     and one pixel across four cards is the kind of looseness the
     dimensional ruling exists to catch. */
  gap: 7px;
  text-align: center;
  font-family: inherit;
  cursor: pointer;
  width: 100%;
}

/* Selected card: primary border + soft fill (WIZARD_SPEC §1's "selected
   card: primary border, soft fill, check" — this screen's own cards carry
   no check glyph, only the border/fill change, matching WizardPay's drawn
   نقدي card exactly). */
.wiz-pay-card--on {
  border: 1.5px solid var(--primary);
  background: var(--primary-soft);
}

.wiz-pay-card__icon {
  inline-size: 44px;
  block-size: 44px;
  border-radius: 13px;
  background: var(--chip);
  color: var(--muted-2);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.wiz-pay-card__title-row {
  display: flex;
  align-items: center;
  gap: 7px;
}

.wiz-pay-card__title {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
}

.wiz-pay-card__hint {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.6;
}

/* The discount AMOUNT input — shown on `showDiscount`, independent of
   `method` (see _step_pay.html's own comment: the four cards are one row,
   إضافة خصم is not a child of نقدي). No drawn artboard shows this state;
   it is this file's own minimal, token-only extension. */
.wiz-pay-discount {
  margin-block-start: var(--sp-10);
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
}

.wiz-pay-discount label {
  font-size: var(--fs-12);
  color: var(--muted-2);
}

.wiz-pay-discount__input {
  block-size: var(--control-height);
  max-inline-size: 160px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  padding-inline: var(--sp-12);
  font-size: var(--fs-14);
  color: var(--ink);
  direction: ltr;
  text-align: end;
}

/* ---- the amount panel (§3), CASH ONLY ------------------------------- */

.wiz-pay-amount {
  margin-block-start: var(--sp-14);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-6) var(--sp-14);
}

.wiz-amount-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-10);
  padding-block: 7px;
  border-block-end: 1px solid var(--line);
  font-size: 12.5px;
}

.wiz-amount-row--last {
  border-block-end: 0;
}

.wiz-amount-row__label {
  color: var(--muted);
}

.wiz-amount-row__value {
  font-weight: 600;
  color: var(--ink);
}

/* "المتبقي" — computed, never an input (brief's own words) — drawn in the
   artboard's warning-amber, which this product already carries as
   --warning-text for exactly this "money still owed" meaning. */
.wiz-amount-row__value--due {
  font-weight: 700;
  color: var(--warning-text);
}

/* The one editable cell in this panel: المدفوع الآن. Styled to sit like the
   static value beside it (no border/background of its own) rather than
   looking like a form field dropped into a receipt. */
.wiz-amount-input {
  border: 0;
  background: transparent;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
  text-align: end;
  inline-size: 90px;
  direction: ltr;
}

/* --------------------------------------------------------------------------
   #wiz-pay — the server fragment (_pay.html): bank details, hold line,
   policy note, error
   -------------------------------------------------------------------------- */

.wiz-pay-bank {
  margin-block-start: var(--sp-14);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-10) var(--sp-14);
}

.wiz-pay-bank__head {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  margin-block-end: var(--sp-4);
  color: var(--muted-2);
}

.wiz-pay-bank__title {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}

/* THE COPY BUTTON. Text-only, flipping label — core/templates/core/
   website_manage.html's established pattern, matched exactly rather than
   re-invented, because a copy control that changes nothing visible was
   reported DEAD by this product's own crawler (brief's own words). No
   dedicated copy glyph exists in templates/partials/_icon.html, so this is
   not an icon swap — the label flip alone already carries the signal. */
.wiz-pay-copy {
  margin-inline-start: auto;
  border: 0;
  background: transparent;
  color: var(--link);
  font-size: var(--fs-12);
  font-weight: 600;
  cursor: pointer;
  padding: var(--sp-4) var(--sp-8);
  border-radius: var(--radius-xs);
}

.wiz-pay-copy:hover {
  background: var(--chip);
}

/* `bank_details` is ONE free-text field (Property.bank_account_details),
   not the artboard's three discrete rows — see _pay.html's own comment.
   Owner finding 5: clean labelled rows, not a raw text dump — `bank_rows`
   (reservations/templatetags/wizard_bank.py) turns the one field's lines
   into these; a line with no colon falls through to `--plain` instead of
   the label/value pair. */
.wiz-pay-bank__details {
  display: flex;
  flex-direction: column;
  padding-block-start: var(--sp-6);
}

.wiz-pay-bank__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-10);
  padding-block: 5px;
  font-size: 12.5px;
  border-block-end: 1px solid var(--line);
}
.wiz-pay-bank__row:last-child {
  border-block-end: 0;
}

.wiz-pay-bank__row-label {
  flex-shrink: 0;
  color: var(--muted);
}

.wiz-pay-bank__row-value {
  color: var(--ink);
  font-weight: 600;
  text-align: end;
  overflow-wrap: anywhere;
}

/* A line the owner typed with no colon -- shown rather than dropped, but
   without the label/value split that line never gave us. */
.wiz-pay-bank__row--plain {
  justify-content: flex-start;
}
.wiz-pay-bank__row--plain .wiz-pay-bank__row-value {
  text-align: start;
  font-weight: 400;
  color: var(--muted-2);
}

.wiz-pay-bank__empty {
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.7;
}

.wiz-pay-bank__empty a {
  color: var(--link);
  margin-inline-start: var(--sp-4);
}

/* The "بانتظار التحقق" note — the artboard's own compact amber box, kept at
   its own exact values rather than the page-level `.alert` (§5), which is
   padded for a much larger message. */
.wiz-pay-note {
  font-size: 11px;
  color: var(--warning-text);
  background: var(--warning-bg);
  border: 1px solid var(--warning-border);
  border-radius: var(--radius-sm);
  padding: 7px var(--sp-10);
  margin-block-start: var(--sp-6);
  line-height: 1.7;
}

.wiz-pay-later {
  margin-block-start: var(--sp-14);
  font-size: 12.5px;
  color: var(--muted-2);
  background: var(--chip);
  border-radius: var(--radius-sm);
  padding: var(--sp-10) var(--sp-12);
  line-height: 1.7;
}

.wiz-pay-policy {
  font-size: 11.5px;
  color: var(--muted);
  margin-block-start: var(--sp-10);
  line-height: 1.6;
}

/* ==========================================================================
   THE LIVE SUMMARY COLUMN (§0) — .wiz__aside and its .wiz__aside-* children
   Present on all three steps; shared shell structure is wizard.css's
   `.wiz__body`/`.wiz__content` (the row that holds this column beside the
   step). This file owns everything inside the 300px column itself.
   ========================================================================== */

.wiz__aside {
  inline-size: 300px;
  flex-shrink: 0;
  border-inline-start: 1px solid var(--line);
  background: var(--surface-2);
  padding: var(--sp-16);
  display: flex;
  flex-direction: column;
  gap: var(--sp-12);
  overflow-y: auto;
}

.wiz__aside-guest,
.wiz__aside-service {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-12) var(--sp-14);
}

.wiz__aside-guest-row {
  display: flex;
  align-items: center;
  gap: var(--sp-10);
}

.wiz__aside-guest-avatar {
  inline-size: 36px;
  block-size: 36px;
  border-radius: var(--radius-pill);
  background: var(--primary-soft);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 13px;
  flex-shrink: 0;
}

.wiz__aside-guest-text {
  line-height: 1.4;
  min-inline-size: 0;
  flex: 1;
}

.wiz__aside-guest-name {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}

.wiz__aside-guest-phone {
  font-size: 11px;
  color: var(--muted);
}

/* Neither drawn in either artboard this build read — both `guestSkipped`
   and "no guest chosen yet" (steps 1/2) reuse the same card shell with
   worded content instead. Flagged in the hand-off. */
.wiz__aside-guest-empty {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  color: var(--muted);
  font-size: 12.5px;
}

.wiz__aside-service-head {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  margin-block-end: var(--sp-6);
}

.wiz__aside-service-title {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}

.wiz__aside-service-tag {
  margin-inline-start: auto;
  font-size: 10px;
  font-weight: 700;
  color: var(--tag-text);
  background: var(--tag-bg);
  border-radius: var(--radius-pill);
  padding: 1px var(--sp-8);
  flex-shrink: 0;
}

.wiz__aside-service-row {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-10);
  font-size: 11.5px;
  padding-block: var(--sp-4);
  color: var(--muted);
}

.wiz__aside-service-value {
  font-weight: 600;
  color: var(--muted-2);
}

.wiz__aside-service-total {
  display: flex;
  justify-content: space-between;
  border-block-start: 1px solid var(--line);
  margin-block-start: var(--sp-6);
  padding-block-start: var(--sp-8);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}

.wiz__aside-service-empty {
  font-size: 12.5px;
  color: var(--muted);
  text-align: center;
  padding-block: var(--sp-8);
}

.wiz__aside-footer {
  margin-block-start: auto;
  display: flex;
  flex-direction: column;
  gap: var(--sp-10);
}

.wiz__aside-due {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-10) var(--sp-14);
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
}

/* Reused by _done.html's own `عرض الحجز` / `حجز آخر` — the SAME control,
   not a second one, since WizardDone draws the identical 42px pair. */
/* Step 2's date fields, shown inside this column rather than in a second
   one beside it -- see the summary template's own note.

   OWNER FINDING 6 (wizard polish round): this was `gap: 9px`, a value this
   rule's own comment claimed was "the column's own" rhythm but was not --
   WizardDate.dc.html draws these fields as DIRECT children of the 300px
   aside itself (no wrapping div of their own), so every one of them sits
   in the SAME 12px gap as the guest card above and the footer below. The
   measured live column had every other pitch at 12px (or the footer's own
   10px) and only this nested wrapper's rows at 9px -- the exact "uneven,
   cramped" row rhythm the owner named. `var(--sp-12)`, matching both the
   artboard and `.wiz__aside`'s own `gap`. */
.wiz__aside-dates {
  display: flex;
  flex-direction: column;
  gap: var(--sp-12);
}

.wiz__aside-btn {
  block-size: 42px;
  /* ZERO, and it has to be said rather than left out. The shell-fix round's
     `button { background: none; border: 0 }` reset clears the user agent's
     colour and its 3D border -- it does NOT clear the user agent's
     `padding: 1px 6px`, which this fixed-height flex-centred control then
     inherits. The dimensional pass read it as 1px 6px against a drawn 0. */
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  font-size: 13.5px;
  font-weight: 700;
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  width: 100%;
}

.wiz__aside-btn--primary {
  background: var(--primary);
  color: var(--on-primary);
}

.wiz__aside-btn--primary:hover {
  background: var(--primary-hover);
}

.wiz__aside-btn--primary:disabled {
  background: var(--chip-2);
  color: var(--chevron);
  cursor: not-allowed;
}

.wiz__aside-btn--outline {
  border-color: var(--border);
  background: var(--surface);
  color: var(--muted-2);
  font-weight: 600;
  /* 44, where the filled variant is 42 -- and the two pixels are the
     BORDER. The artboard draws both at `height: 42px`, but only this one
     has a 1px border, and its artboards have no `box-sizing` reset: the
     outlined control's outer size there is 44. This product is
     `border-box`, so matching the drawing means saying 44 out loud. */
  block-size: 44px;
}

.wiz__aside-btn--outline:hover {
  background: var(--bg);
  color: var(--ink);
}

/* ==========================================================================
   SUCCESS (WizardDone.dc.html)
   ========================================================================== */

/* The artboard draws the success state in its OWN narrower (460px) floating
   panel, not the 1024px step panel. wizard.css's `.wiz__panel` is fixed-
   width and is the shell's file, outside this build's scope, so it cannot
   be narrowed from here — `.wiz-done` instead centres a 460px card INSIDE
   the full-width panel. Flagged in the hand-off as a structural divergence
   only the shell's owner can close. */
.wiz-done {
  inline-size: 460px;
  max-inline-size: 100%;
  margin-inline: auto;
  margin-block: var(--sp-32) var(--sp-20);
  padding: 28px 26px 22px;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: var(--radius-xl);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-10);
}

/* The same green check circle wizard.css's own header uses for a DONE step
   (`.wiz__step--done .wiz__step-mark`) — reused at a larger size rather
   than drawing the artboard's separate border colour, which has no token. */
.wiz-done__icon {
  inline-size: 56px;
  block-size: 56px;
  border-radius: var(--radius-pill);
  background: var(--success-bg);
  color: var(--success-text);
  display: flex;
  align-items: center;
  justify-content: center;
}

.wiz-done__title {
  font-size: var(--fs-17);
  font-weight: 700;
  color: var(--ink);
}

.wiz-done__ref {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--sp-10);
}

.wiz-done__ref-label {
  font-size: var(--fs-12);
  color: var(--muted);
}

.wiz-done__ref-value {
  font-weight: 700;
  color: var(--ink);
}

.wiz-done__card {
  align-self: stretch;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--sp-4) var(--sp-14);
  margin-block-start: var(--sp-6);
}

.wiz-done__row {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-10);
  padding-block: 7px;
  border-block-end: 1px solid var(--line);
  font-size: 12.5px;
}

.wiz-done__row:last-child {
  border-block-end: 0;
}

.wiz-done__row-label {
  color: var(--muted);
}

.wiz-done__row-value {
  font-weight: 600;
  color: var(--ink);
  text-align: end;
}

/* «الدفعة مسجّلة · بانتظار التحقق» -- owner ruling, 11 Oct 2026. A note,
   not a row: it has no label/value pair, so it does not use the row's
   space-between. --warning-text on the card's own ground, because
   "recorded but not yet counted" is exactly the state that token names
   everywhere else in this product. */
.wiz-done__row--note {
  justify-content: center;
  border-block-end: 0;
}

.wiz-done__note {
  color: var(--warning-text);
  font-size: var(--fs-12);
  font-weight: 600;
}

/* «نسخ الملخص» -- owner finding 7, 11 Oct 2026. Same visual weight as
   `.wiz-pay-copy` (the bank-details copy) because it is the same control
   doing the same job, one screen later: a quiet secondary action beside a
   block of facts, never competing with «عرض الحجز» below it. Its own
   class rather than reusing `.wiz-pay-copy` only because that one is
   `margin-inline-start: auto` inside a flex head, and this one centres
   itself in a column.

   THE LOOK IS SHARED WITH `.wiz-done__doc-action` BELOW through this
   combined selector -- NOT by `.wiz-done__doc-action` reusing this class
   in markup. `.wiz-done__copy` means "the button that copies the booking
   summary" (`core/test_e2e_smoke.py` locates exactly that button by this
   class, to read `data-copy-text` off it); the three download/share
   controls below are not that button, and giving them the same class
   broke the E2E smoke path's strict-mode lookup (four elements where it
   expected one) the one time that was tried. */
.wiz-done__copy,
.wiz-done__doc-action {
  border: 0;
  background: transparent;
  color: var(--link);
  text-decoration: none;
  font-size: var(--fs-12);
  font-weight: 600;
  cursor: pointer;
  padding: var(--sp-6) var(--sp-10);
  border-radius: var(--radius-xs);
}

.wiz-done__copy:hover,
.wiz-done__doc-action:hover {
  background: var(--chip);
}

/* `.wiz-done__copy` ALONE keeps its own positioning: it is a lone direct
   child of the `.wiz-done` flex column, so it centres itself and carries
   its own top margin. `.wiz-done__doc-action` needs neither -- its parent
   `.wiz-done__docs` (below) is the thing that centres and spaces ITS
   children, as a row rather than a column. */
.wiz-done__copy {
  align-self: center;
  margin-block-start: var(--sp-8);
}

/* «تنزيل الفاتورة» / «تنزيل العقد» / «مشاركة رابط المستندات» -- lane DOCS,
   the sharing-controls commission, 15 Oct 2026. A row of up to three
   `.wiz-done__doc-action` controls, wrapping on a narrow phone sheet
   rather than overflowing it. */
.wiz-done__docs {
  align-self: stretch;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-4);
}

.wiz-done__warnings {
  align-self: stretch;
  margin-block-start: var(--sp-10);
  margin-block-end: 0;
}

.wiz-done__warnings ul {
  margin: 0;
  padding-inline-start: var(--sp-16);
}

.wiz-done__actions {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin-block-start: var(--sp-10);
}

.wiz-done__close {
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted-2);
  background: transparent;
  border: 0;
  cursor: pointer;
  /* NO PADDING. The artboard draws «إغلاق» as a bare 12.5px/600 line under
     the two buttons -- not a third button. The 8px block padding built here
     made it 37px tall against a drawn 21, which reads as a third control
     competing with the two above it. */
  padding: 0;
}

.wiz-done__close:hover {
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   PHONE (<640px) — the wizard becomes a full sheet (wizard.css §8); the
   aside is not a side column there, it is the sheet's own sticky footer
   section. Stacked under the step content, full-width controls.
   -------------------------------------------------------------------------- */
@media (max-width: 639px) {
  .wiz__aside {
    inline-size: auto;
    border-inline-start: 0;
    border-block-start: 1px solid var(--line);
    /* Not a scroller of its own at this width: it is not a column beside
       the step, it is the rest of the sheet's one column. */
    overflow: visible;
  }

  /* ---- the pinned footer ---------------------------------------------- */
  /* MobileWizard draws «المبلغ المستحق» and the step's two buttons pinned to
     the bottom edge above a rule.

     `position: fixed`, AND NOT `sticky`, and the difference is the whole
     reason this works. `.wiz__aside-footer` is the last child of the aside,
     which is the last child of the scrolling body -- so a sticky footer only
     appears once its CONTAINING BLOCK intersects the scrollport. On step 1
     the unit list is 1,500px tall and the aside begins far below the fold,
     so a sticky footer would be invisible until the reader had already
     scrolled past everything it exists to let them skip. Fixed to the
     viewport is unconditional, which is what "pinned" means.

     It escapes `.wiz__panel`'s `overflow: hidden` because overflow on an
     ancestor does not clip a fixed descendant (no ancestor here carries a
     transform or `contain`), and it stays inside the frame's z-index 90
     stacking context, so it is above the body without competing with the
     shell. */
  .wiz__aside-footer {
    position: fixed;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 2;
    display: grid;
    /* The two buttons on ONE row, «التالي» taking the room -- the
       artboard's own arrangement. Stacking them costs a whole 56px band on
       the screen with the least of it. */
    grid-template-columns: 1fr auto;
    gap: var(--sp-10);
    align-items: center;
    margin: 0;
    /* `var(--safe-area-bottom)`, not an inline `env()`: the token is the one
       point of truth for this inset (tokens.css), which is also what makes
       it testable -- a test can override the token to a real device's 34px
       and measure the footer move, where an inline `env()` would stay 0 in
       both engines this project's tooling runs. */
    padding-block: var(--sp-12) calc(var(--sp-12) + var(--safe-area-bottom));
    /* AND THE INLINE PAIR, for the same reason the block-end one is here:
       `position: fixed` is positioned against the initial containing
       block, not `.wiz__panel` -- it does not inherit any ancestor's
       inline safe-area padding, it spans the unsafe side areas itself. A
       landscape phone is still under this file's 640px breakpoint, so the
       buttons would sit under the notch at that width without this. */
    padding-inline: calc(var(--sp-16) + var(--safe-area-start))
                    calc(var(--sp-16) + var(--safe-area-end));
    border-block-start: 1px solid var(--line);
    background: var(--surface-2);
  }
  .wiz__aside-due { grid-column: 1 / -1; }
  .wiz__aside-btn--primary { grid-column: 1; }
  .wiz__aside-btn--outline { grid-column: 2; }
  .wiz__aside-btn {
    min-block-size: var(--control-height);
    margin: 0;
    /* `inline-size: auto`, UNDOING the base rule's `width: 100%`.
       MEASURED at 390px: «السابق» rendered **38px wide** beside a 310px
       «التالي», its own label overflowing it. The footer's `auto` track sizes
       to the item's contribution, and an item whose width is a PERCENTAGE OF
       THAT TRACK contributes nothing to resolve it -- the percentage is
       cyclic, so it behaves as `auto` for sizing and then resolves against a
       track that was sized without it. The artboard draws the pair at roughly
       60/35; with this they come out 258/90. */
    inline-size: auto;
    padding-inline: var(--sp-16);
  }

  /* THE GUTTER THE PINNED FOOTER NEEDS, and the number is measured rather
     than guessed: at 390px the footer's own content is 12 + 19 (the due
     row) + 10 + 44 + 12 = 97px, before any safe-area inset.

     CORRECTED (device-matrix round, 15 Oct 2026): this used to say "112px
     with the inset a notched iPhone reports", which assumed roughly 15px.
     That was never a real measurement -- `viewport-fit=cover` was not on
     the viewport meta yet, so the footer's `env()` was inert and the
     inset was always 0 in practice. A notched iPhone actually reports
     34px in portrait (`IPHONE_SAFE_AREA_BOTTOM_PX`,
     `core/device_profiles.py`), so the true worst case was 97 + 34 =
     131px against a static 148px reserve -- 17px of clearance, not 36.

     Now that the inset is real, the reserve CARRIES it explicitly rather
     than trying to absorb an unknown device's worth inside a fixed
     number: 148px is the clearance for the 97px of content, and
     `var(--safe-area-bottom)` is added on top, so the gutter still has
     its ~17px of clearance at every inset the token is ever set to,
     instead of running out on whichever device reports more than 15px.

     `_review/mobile-night/overlays.py` measures the real footer against
     this reserve on every run, so a footer that grows past it is a failing
     check rather than a card nobody can read. */
  .wiz__body { padding-block-end: calc(148px + var(--safe-area-bottom)); }
  /* The success body has no footer under it -- `.wiz__body` is `x-show`n
     off when `done` is true and takes the pinned band with it -- so the
     gutter would be 148px of nothing below «حجز آخر». */
  .wiz__body--done { padding-block-end: 0; }

  /* ---- touch targets inside the three steps -------------------------- */
  /* The owner's words: "every one of its three steps, including the month
     calendar, unit cards, price-choice cards, guest search and the payment
     cards, must be fully usable with one thumb". These are the controls
     the phone sweep measured under 44px. */
  .wiz-month-nav {
    inline-size: var(--control-height);
    block-size: var(--control-height);
  }
  .wiz-guest-skip,
  .wiz-guest-new-btn {
    min-block-size: var(--control-height);
    padding-inline: var(--sp-10);
  }
  .wiz-guest-search { min-block-size: var(--control-height); }
  .wiz-guest-search__input { block-size: 100%; }
  .wiz-guest-chosen__clear {
    inline-size: var(--control-height);
    block-size: var(--control-height);
  }




  .wiz-pay-cards {
    grid-template-columns: 1fr;
  }

  .wiz-done {
    inline-size: auto;
    border: 0;
    border-radius: 0;
    margin-block: 0;
    padding: var(--sp-20) var(--sp-16);
  }
}


/* The wizard's own small target, measured by the phone sweep at 51x21 and
   72x21: «تخطّي الآن», one of step 1's three guest doors. The other two are
   handled in §8's phone block; this one is here because `.wiz-guest-skip`'s
   base rule is declared below that block and would otherwise win. */
@media (max-width: 639px) {
  .wiz-guest-skip {
    min-block-size: var(--control-height);
    display: inline-flex;
    align-items: center;
  }
}

/* ==========================================================================
   TOUCH TARGETS (device-matrix round, 15 Oct 2026)

   `@media (pointer: coarse)` and NOT a width breakpoint, which is the whole
   point: a target's required size follows the INPUT DEVICE, not the viewport.
   The owner's 40px floor is scoped to touch profiles for that reason, and an
   iPad in landscape is 1194px wide -- the DESKTOP shell -- and still driven
   by a thumb. A width rule misses exactly that case, and it is the case the
   matrix found the most offenders in.

   Every mouse rendering is byte-for-byte unchanged, so no desktop artboard is
   contradicted. Where a phone artboard draws a smaller control, the owner's
   40px ruling is the newer and more specific instruction and wins for touch;
   recorded in docs/design/CHANGELOG.md rather than left unexplained.

   `min-block-size` beats an explicit `block-size` (the minimum wins over the
   used value), so these need no `!important` and no selector weight games.
   ========================================================================== */
@media (pointer: coarse) {
  /* `.wiz-guest-skip` measured 50-72 x 21.25 and `.wiz__close` 32x32 -- both
     on the booking wizard, which is the flow a guest-facing booking actually
     depends on. */
  .wiz__close,
  .wiz-guest-skip { min-block-size: 40px; min-inline-size: 40px; }
}
