/* KASANE design layer
   Loaded after kasane.css so the mobile design wins reliably. */

:root {
  /* Base visual and iOS Settings tokens belong to kasane.css.  This layer
     owns only design-layer layout tokens, so load order cannot silently
     change a shared value. */
  --primary: #651868;
  --inventory-thumbnail-radius: 10px;
  --inventory-detail-image-size: 98px;
  --inventory-status-width: 78px;
  --inventory-detail-columns: var(--inventory-detail-image-size) minmax(0, 1fr);
  --page-content-gap: 12px;
  /* The one outer margin of every screen (Q4, owner 2026-10-02「必ずそろえる」):
     20px, iOS's edge-to-card gutter for grouped lists. Screens never write
     their own; scripts/check-layout-contract.mjs fails the build if one does. */
  --mobile-page-gutter: 20px;
  --page-gutter: var(--mobile-page-gutter);
  --reservation-table-min-width: 640px;
  --reservation-table-cell-pad: 10px;
  --home-schedule-compact-row-height: 36px;
  --list-row-height: 40px;
  --home-schedule-visible-rows: 3;
  --home-card-head-height: 48px;
  --home-schedule-row-gap: 6px;
  --home-schedule-list-inset-block: 8px;
  --home-schedule-list-height: calc(
    (var(--home-schedule-compact-row-height) * var(--home-schedule-visible-rows)) +
    (var(--home-schedule-row-gap) * (var(--home-schedule-visible-rows) - 1)) +
    (var(--home-schedule-list-inset-block) * 2)
  );
  --schedule-empty-min-height: var(--home-schedule-list-height);
  --schedule-divider-gap: 8px;
  --bottom-nav-label-size: 12px;
  --bottom-nav-label-weight: 600;
  --settings-list-shadow: var(--card-shadow);
  /* One nav-to-content distance for every ManagementScreen destination.  The
     screen shell owns this rather than requiring each detail page to add its
     own first-child margin or padding. */
  --management-content-start-gap: 20px;
  --settings-heading-inline-inset: 0px;
  --settings-card-padding: var(--card-padding-large);
  --settings-card-compact-padding: var(--card-padding-small);
  /* The label takes the width it needs, up to 60% of the row, and the value
     the rest: 「定期スナップショット」 beside 「0件」 stays on one line. A fixed
     0.85fr share wrapped every label longer than about seven characters
     however short its value (2026-09-28). */
  --settings-label-value-columns: fit-content(60%) minmax(0, 1fr);
  /* A complete numeric date and a choice fit beside a four-character label at 390px. */
  --settings-compact-control-width: 178px;
  --settings-page-inset: 20px;
  --settings-text-inset: 40px;
  --settings-card-footnote-gap: 8px;
  --settings-footnote-section-gap: 32px;
  --settings-footnote-size: 13px;
  --settings-footnote-line-height: 17px;
  --settings-switch-width: 63px;
  --settings-switch-height: 28px;
  --settings-switch-thumb-width: 37px;
  --settings-switch-thumb-height: 24px;
  --settings-switch-inset: 2px;
  --ui-page-title-size: 17px;
  --ui-page-title-weight: 600;
  --ui-page-title-line-height: 22px;
  --ui-section-title-size: 17px;
  --ui-section-title-weight: 600;
  --ui-section-title-line-height: 22px;
  --ui-row-label-size: 17px;
  --ui-row-label-weight: 400;
  --ui-row-label-line-height: 22px;
  --ui-supporting-text-size: 14px;
  --ui-supporting-text-weight: 400;
}

/* A wider screen with a mouse keeps its wider margins, set here once. */
@media (min-width: 700px) and (hover: hover) and (pointer: fine) {
  :root {
    --page-gutter: 34px;
  }
}

@media (min-width: 768px) and (hover: hover) and (pointer: fine) {
  :root {
    --page-gutter: 44px;
  }
}

.main {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--app-system-font);
}

/* Status contains only local command counts. It stays clear of the mobile
   navigation capsule and needs no customer or reservation text. */
.offline-sync-indicator {
  position: fixed;
  z-index: 10020;
  right: max(16px, env(safe-area-inset-right));
  bottom: calc(102px + env(safe-area-inset-bottom));
  margin: 0;
  border: 1px solid rgba(101, 24, 104, 0.16);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: none;
  color: var(--accent);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  padding: 10px 12px;
}

.offline-sync-indicator.is-attention {
  border-color: rgba(205, 70, 67, 0.24);
  background: var(--warning-bg);
  color: var(--danger);
}

@media (min-width: 768px) and (hover: hover) and (pointer: fine) {
  .offline-sync-indicator {
    right: 20px;
    bottom: 20px;
  }
}

/* Reception history uses only the non-PII audit summary. */
.reservation-activity-panel {
  display: grid;
  gap: 0;
}

.reservation-activity-list {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.reservation-activity-list li {
  display: grid;
  gap: 4px;
  padding: 12px 16px;
}

/* Dividers go between entries only (li + li in kasane.css). A divider on the
   first entry drew a grey line along the white card's top edge. */

.reservation-activity-list li > div {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
}

.reservation-activity-list strong {
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
}

.reservation-activity-list span,
.reservation-activity-list small {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
}

/* The reservation form is a dedicated reception workspace, not a small panel
   inside the ledger. Header and form controls remain reachable on long forms. */
body.reservation-registration-open {
  overflow: hidden;
}

.reservation-registration-screen {
  position: fixed;
  z-index: 10050;
  inset: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  overflow: hidden;
  background: var(--bg);
}

.reservation-registration-header {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 44px;
  align-items: center;
  min-height: calc(44px + var(--management-header-top-gap) + env(safe-area-inset-top));
  padding: calc(var(--management-header-top-gap) + env(safe-area-inset-top)) var(--page-gutter) 0;
  background: var(--accent);
  color: var(--paper);
}

.reservation-registration-header h2 {
  margin: 0;
  color: inherit;
  font-size: 18px;
  font-weight: 500;
  text-align: center;
}

.reservation-registration-close {
  display: grid;
  width: 44px;
  height: 44px;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--paper);
  color: var(--accent);
  cursor: pointer;
}

.reservation-registration-close .ti {
  font-size: 28px;
  line-height: 1;
}

.reservation-registration-scroll {
  min-height: 0;
  overflow-x: hidden;
  overflow-y: hidden;
}

.reservation-registration-scroll::-webkit-scrollbar {
  display: none;
}

/* The form's own wrapper (it also holds the step-3 buttons under the panel)
   sat between this frame and the panel with no height of its own, so the
   panel's height: 100% resolved to its content: the form grew past the frame,
   whose overflow is hidden, and nothing scrolled (2026-09-27, measured 1005px
   of form in an 872px frame). The wrapper fills the frame, the panel takes
   what the step-3 buttons leave, and the panel's own content area scrolls. */
.reservation-registration-scroll .reservation-form-shell {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  height: 100%;
  min-height: 0;
}

.reservation-registration-scroll .reservation-form-panel {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 0;
  width: min(780px, 100%);
  height: 100%;
  margin: 0 auto;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.reservation-registration-scroll .reservation-stepper {
  position: relative;
  z-index: 1;
  min-height: 72px;
  margin: 0;
  border-bottom: 1px solid var(--line);
  background: var(--bg);
  padding: 18px max(16px, env(safe-area-inset-right)) 16px max(16px, env(safe-area-inset-left));
  box-shadow: none;
}

.reservation-registration-scroll .reservation-form-scroll-content {
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: none;
  padding: 20px max(16px, env(safe-area-inset-right)) calc(32px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
  scrollbar-width: none;
}

.reservation-registration-scroll .reservation-form-scroll-content::-webkit-scrollbar {
  display: none;
}

.reservation-registration-scroll .reservation-step-body {
  width: min(680px, 100%);
  margin: 0 auto;
}

/* Shared detail rows own their inset and divider; the confirmation card
   must not add a second inset around them. */
.reservation-confirm-detail-list {
  gap: 0;
  overflow: hidden;
  padding: 0;
}

.reservation-kind-note {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.6;
}

@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {

  .reservation-registration-screen {
    grid-template-rows: auto minmax(0, 1fr);
  }

  .reservation-registration-header {
    min-height: calc(44px + var(--management-header-top-gap) + env(safe-area-inset-top));
    padding: calc(var(--management-header-top-gap) + env(safe-area-inset-top)) var(--page-gutter) 0;
  }

  .reservation-registration-scroll .reservation-stepper {
    min-height: 68px;
    padding: 16px 16px 14px;
  }

  .reservation-registration-scroll .reservation-form-panel {
    width: 100%;
  }

  .reservation-registration-scroll .reservation-form-scroll-content {
    padding: 16px 16px calc(24px + env(safe-area-inset-bottom));
  }

  .reservation-registration-scroll .reservation-step-body {
    width: 100%;
    border: 0;
    box-shadow: none;
  }
}

/* Home */
.home-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 67px;
  gap: 10px;
}

.home-clock-stack {
  display: grid;
  width: 134px;
  gap: 0;
  justify-items: start;
}

.home-date {
  color: #651868;
  font-size: 20px;
  font-weight: 500;
  line-height: 24px;
  white-space: nowrap;
}

.home-time {
  color: #651868;
  font-size: 36px;
  font-weight: 500;
  line-height: 43px;
}

.home-top-actions {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  min-width: 0;
}

.home-dresser-warning {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 138px;
  min-height: 33px;
  gap: 8px;
  border: 0;
  border-radius: 20px;
  background: var(--warning-bg);
  color: var(--danger);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  padding: 8px 12px;
  white-space: nowrap;
}

.ui-icon-img {
  width: 16px;
  height: 16px;
}

.notice-button {
  position: relative;
  display: grid;
  width: 52px;
  height: 52px;
  flex: 0 0 52px;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--paper);
  color: #651868;
  box-shadow: none;
}

/* The bell file is navy (#1b2d6b), and an <img> cannot take a colour from
   CSS, so it read navy beside the purple of everything else on Home
   (2026-09-27). It is used as a mask and painted in the button's colour,
   the accent. */
.notice-button-img {
  width: 20px;
  height: 20px;
  background: currentColor;
  -webkit-mask: url("/img/icon_notification.svg") center / contain no-repeat;
  mask: url("/img/icon_notification.svg") center / contain no-repeat;
}

.notice-badge {
  position: absolute;
  top: 0;
  right: 0;
  display: grid;
  min-width: 24px;
  height: 24px;
  place-items: center;
  border-radius: 50%;
  background: var(--danger);
  color: var(--paper);
  font-size: 14px;
  font-weight: 700;
}

.warning-grid {
  display: none;
}

.home-card.panel {
  overflow: hidden;
  width: 100%;
  border: 0;
  border-radius: 20px;
  background: var(--paper);
  box-shadow: none;
  padding: 0;
}

.home-card-head,
.home-dashboard > .panel > .panel-head {
  display: grid;
  height: 32px;
  min-height: 32px;
  place-items: center;
  border: 0;
  border-radius: 20px 20px 0 0;
  background: #651868;
  color: var(--paper);
  padding: 6px 0;
}

.home-card-head h2,
.home-dashboard > .panel > .panel-head h2 {
  margin: 0;
  color: var(--paper);
  font-size: 14px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}

.home-schedule-panel {
  display: grid;
  min-height: 308px;
}

.schedule-count-badges {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.schedule-count-badges .schedule-count-pair {
  display: inline-flex;
  align-items: center;
  min-height: auto;
  gap: 6px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-size: 14px;
  font-weight: 700;
  line-height: 20px;
  padding: 0;
}

.schedule-count-pair b {
  display: inline-flex;
  align-items: center;
  min-height: 18px;
  border-radius: 20px;
  background: var(--muted);
  color: var(--paper);
  font-size: 10px;
  font-weight: 700;
  line-height: 14px;
  padding: 2px 6px;
}

.schedule-count-pair em {
  color: var(--ink);
  font-size: 14px;
  font-style: normal;
  font-weight: 700;
  line-height: 20px;
}

.timeline-list,
.week-list {
  display: grid;
  gap: 8px;
  padding: 8px 10px;
}

.home-schedule-divider {
  height: 1px;
  background: var(--line);
  margin: 0 10px;
}

.home-schedule-panel .empty-state {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--line);
  font-size: 10px;
  font-weight: 500;
  padding: 10px;
  text-align: center;
}

.timeline-row,
.week-row {
  display: flex;
  min-height: var(--settings-row-height);
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: 4px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: none;
  color: var(--ink);
  padding: 10px var(--settings-list-inset);
}

.timeline-row {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
}

.timeline-row time,
.week-row > strong {
  color: var(--ink);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.3;
}

.schedule-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: 8px;
}

.schedule-title-row strong,
.schedule-title-row span {
  min-width: 0;
  overflow: hidden;
  color: var(--ink);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.timeline-row p,
.timeline-side {
  color: var(--ink);
  font-size: 14px;
  font-weight: 400;
}

/* This is the rule that actually wins for radius: it loads after kasane.css,
   so its 20px beat that file's 999px on every real render, which is why the
   badge read as a rounded rectangle instead of a pill despite kasane.css's
   own rule already saying 999px (P056). */
.schedule-warning-badge,
.timeline-row .schedule-warning-badge,
.week-row .schedule-warning-badge {
  flex: 0 0 auto;
  border-radius: 999px;
  background: var(--warning-bg);
  color: var(--danger);
  font-size: 12px;
  font-style: normal;
  font-weight: 700;
  line-height: 16px;
  padding: 4px 10px;
}

.home-inventory-summary {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  padding: 10px;
  min-height: 134px;
}

.home-inventory-summary .summary-card {
  display: grid;
  min-height: 60px;
  place-items: center;
  border: 0;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: var(--paper);
  box-shadow: none;
  padding: 8px;
  text-align: center;
}

.home-inventory-summary .summary-card:nth-child(3n) {
  border-right: 0;
}

.home-inventory-summary .summary-card:nth-last-child(-n + 3) {
  border-bottom: 0;
}

.home-inventory-summary .summary-card span {
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  line-height: 14px;
}

.home-inventory-summary .summary-card strong {
  color: var(--ink);
  font-size: 24px;
  font-weight: 700;
  line-height: 35px;
}

.home-inventory-summary .danger-summary span,
.home-inventory-summary .danger-summary strong {
  color: var(--danger);
}

.home-inventory-summary .danger-summary {
  background: var(--paper);
  border-color: var(--line);
}

.home-action-grid {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.home-action-button {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  min-height: 40px;
  border: 0;
  border-radius: 20px;
  background: #651868;
  color: var(--paper);
  box-shadow: none;
  font-size: 14px;
  font-weight: 700;
  padding: 10px;
  text-align: center;
}

/* Inventory */
.inventory-sticky-header {
  --inventory-side-control-width: 116px;
  position: sticky;
  top: 0;
  z-index: 90;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 8px;
  min-height: 223px;
  margin: -26px -18px 16px;
  border: 0;
  background: #651868;
  box-shadow: none;
  padding: 80px var(--page-gutter) 20px;
}

.inventory-title-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 24px;
  margin-bottom: 22px;
}

.inventory-title-row h1 {
  margin: 0;
  color: var(--paper);
  font-size: 16px;
  font-weight: 700;
  line-height: 24px;
}

.inventory-title-row .head-count {
  display: inline-flex;
  height: 24px;
  align-items: center;
  margin: 0;
  color: var(--paper);
  font-size: 12px;
  font-weight: 700;
  line-height: 24px;
}

.inventory-search-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  width: 100%;
}

/* The search field, view switch, filter chips and sort control are white on
   the purple header and read as shapes without an outline; the grey border
   only added noise (2026-09-27: 「ボーダーがなくても成り立つものにはつけない」). */
.inventory-search-field {
  min-height: 36px;
  height: 36px;
  border: 0;
  border-radius: 999px;
  background: var(--paper);
  box-shadow: none;
  padding: 0 16px;
  gap: 8px;
}

.inventory-search-field i {
  color: var(--ink);
  font-size: 18px;
}

.inventory-search-field input {
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
}

.inventory-search-field input::placeholder {
  color: var(--line);
}

.view-mode-switch {
  display: flex;
  width: var(--inventory-side-control-width);
  flex: 0 0 var(--inventory-side-control-width);
  height: 36px;
  align-items: center;
  justify-content: center;
  gap: 0;
  border-radius: 999px;
  background: var(--paper);
  border: 0;
  box-shadow: none;
  padding: 2px;
}

.view-mode-button {
  display: grid;
  width: auto;
  height: 32px;
  flex: 1 1 0;
  place-items: center;
  border: 0;
  border-radius: 999px;
  background: transparent;
  padding: 0;
  transition: background-color 160ms ease-out;
}

.view-mode-button.is-active {
  background: #651868;
}

.view-mode-img {
  display: block;
  width: 18px;
  height: 18px;
  object-fit: contain;
}

.inventory-filter-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--inventory-side-control-width);
  column-gap: 10px;
  width: 100%;
  height: 36px;
  min-height: 36px;
  border: 0;
  overflow: hidden;
  padding: 0;
  background: #651868;
  box-shadow: none;
  outline: 0;
  isolation: isolate;
}

.inventory-filter-row::after {
  content: none;
}

.inventory-filter-scroll {
  position: relative;
  z-index: 1;
  display: flex;
  width: 100%;
  min-width: 0;
  height: 36px;
  gap: 4px;
  overflow-x: auto;
  overflow-y: hidden;
  /* none, not contain. contain only stops a scroll from chaining to the
     document; the strip itself is still free to rubber-band under a finger,
     on both axes. This is the app's only horizontally scrollable region, so
     it was also the only place a sideways drag could bounce anything (P058). */
  overscroll-behavior: none;
  padding: 0;
  background: #651868;
  contain: paint;
  clip-path: inset(0);
  scroll-padding-right: 0;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.inventory-filter-scroll::-webkit-scrollbar {
  display: none;
}

.inventory-filter-row .filter-chip {
  display: inline-flex;
  width: 132px;
  flex: 0 0 132px;
  align-items: center;
  box-sizing: border-box;
  height: 36px;
  min-height: 36px;
  gap: 6px;
  border: 0;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  padding: 0 12px;
  white-space: nowrap;
  box-shadow: none;
  outline: 0;
}

.inventory-filter-row .filter-chip.is-selected {
  border-color: var(--line);
  background: var(--paper);
  color: var(--ink);
}

.inventory-filter-row .filter-chip > span:first-child {
  min-width: 0;
  flex: 0 0 auto;
}

.inventory-filter-row .filter-chip select {
  width: 0;
  min-width: 0;
  flex: 1 1 auto;
  height: 20px;
  min-height: 20px;
  max-width: none;
  border: 0;
  background: transparent;
  color: #651868;
  font-size: 14px;
  font-weight: 700;
  line-height: 20px;
  outline: 0;
  padding: 0;
  text-align: left;
  appearance: none;
}

.inventory-filter-row .filter-chip .filter-divider {
  display: block;
  width: 1px;
  height: 14px;
  min-width: 1px;
  flex: 0 0 1px;
  background: var(--line);
}

.inventory-filter-row .filter-arrow-img {
  width: 8px;
  height: 8px;
  object-fit: contain;
}

.inventory-filter-scroll .filter-clear {
  flex: 0 0 auto;
  min-height: 36px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  color: #651868;
  padding: 0 14px;
}

.inventory-sort-control {
  position: relative;
  z-index: 1;
  display: flex;
  width: 100%;
  height: 36px;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 0;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  overflow: hidden;
  padding: 0 12px;
  box-shadow: none;
  outline: 0;
  isolation: isolate;
}

.inventory-sort-control::before {
  content: none;
}

.inventory-sort-control img {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  object-fit: contain;
}

.inventory-sort-control select {
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-size: 14px;
  font-weight: 700;
  outline: 0;
  appearance: none;
}

.inventory-sort-control:focus,
.inventory-sort-control:focus-within,
.inventory-sort-control select:focus,
.inventory-sort-control select:focus-visible {
  outline: 0;
  box-shadow: none;
}

.inventory-result-count {
  margin: 0 12px 14px;
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
}

.inventory-mode-detail .inventory-card-list {
  display: grid;
  gap: 4px;
}

.inventory-mode-detail .inventory-card {
  position: relative;
  display: grid;
  grid-template-columns: var(--inventory-detail-columns);
  gap: 10px;
  align-items: start;
}

.inventory-mode-detail .inventory-thumb {
  width: var(--inventory-detail-image-size);
  height: var(--inventory-detail-image-size);
  border: 1px solid var(--line);
  border-radius: 20px;
}

.inventory-mode-detail .inventory-card-main {
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 4px;
  min-width: 0;
}

/* A card whose main link is stretched over it, so the whole card opens (owner,
   2026-10-09). Its press feedback is the shared rule in
   interaction-feedback.module.css. The status box is not a link: a touch on it
   reaches the stretched one. */
.settings-card:has(> .card-link) {
  position: relative;
}

.card-link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.inventory-mode-detail .inventory-card-status-box {
  pointer-events: none;
}

.inventory-mode-detail .inventory-card-main .inventory-card-title {
  padding-right: 88px;
}

.inventory-mode-detail .inventory-card-title strong {
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.45;
}

.inventory-mode-detail .inventory-card-title span {
  color: var(--ink);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.45;
}

.inventory-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.inventory-card-tags span {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  padding: 0 12px;
}

/* Every hairline in the app is 1px of var(--line). Blink snaps a 0.5px
   border up to a solid 1 CSS pixel, so every Chromium check rendered a crisp
   line and reported "cannot reproduce" (P037, twice again in P051). WebKit
   instead honours the sub-pixel width and antialiases it, spreading --line
   over partial coverage. This box was raised to a full pixel back then and
   the other 29 sub-pixel hairlines were left, on the reasoning that they sit
   between a white surface and the grey canvas and read on background
   contrast alone -- which is why this box's edge and the edit button's ring
   beside it, both var(--line), looked like different weights on the phone
   and identical in review (P060). They are all 1px now. A full pixel is what
   Blink was already drawing, so this changes nothing on Chrome while giving
   iOS the same visible edge. */
.inventory-card-status-box {
  display: grid;
  position: absolute;
  top: 10px;
  right: 10px;
  overflow: hidden;
  width: 78px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
}

.inventory-card-status-box span {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  min-height: 24px;
  align-items: center;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-size: 10px;
  font-weight: 500;
  padding: 0 12px;
  white-space: nowrap;
}

.inventory-card-status-box span:last-child {
  border-bottom: 0;
}

.inventory-card-status-box strong {
  color: #651868;
  font-size: 12px;
  font-weight: 700;
}

.inventory-gallery-card,
.inventory-text-card {
  position: relative;
}

.inventory-gallery-card .inventory-gallery-item,
.inventory-text-card .inventory-text-row {
  width: 100%;
  height: 100%;
}

/* Bottom navigation */
@media (max-width: 767px), (hover: none) and (pointer: coarse) {
  .main {
    /* Plus the status-bar strip -- see the base .main rule in kasane.css. */
    padding-top: calc(var(--mobile-main-top-gap) + env(safe-area-inset-top));
  }

  .home-dashboard {
    padding-top: 24px;
  }

  .inventory-sticky-header {
    min-height: 176px;
    margin: -8px -18px 16px;
    padding: 28px var(--page-gutter) 16px;
  }

  .inventory-title-row {
    margin-bottom: 14px;
  }

  .inventory-fab-cluster {
    bottom: 172px;
  }

  .inventory-fab-cluster .fab-button {
    bottom: calc(104px + env(safe-area-inset-bottom));
  }

  .sidebar {
    min-height: 80px;
    border-top: 1px solid var(--line);
    background: var(--paper);
    box-shadow: none;
    padding: 0 0 20px;
  }

  .nav {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: center;
    gap: clamp(28px, 11vw, 48px);
  }

  .nav-pill {
    display: none;
  }

  .nav-item {
    width: 28px;
    min-height: 28px;
    gap: 0;
    padding: 0;
    border-radius: 0;
    transform: none;
  }

  .nav-img {
    width: 28px;
    height: 28px;
  }
}

@media (min-width: 600px) and (hover: hover) and (pointer: fine) {
  .home-dashboard {
    width: 100%;
    max-width: none;
    padding-top: 0;
    align-content: start;
  }

  .home-topbar {
    min-height: 80px;
    padding: 0 4px;
  }

  .home-schedule-panel {
    min-height: 0;
  }

  .timeline-row {
    grid-template-columns: 72px minmax(0, 1fr) auto;
  }

  .home-action-grid {
    width: 100%;
  }
}

@media (min-width: 768px) and (hover: hover) and (pointer: fine) {
  .inventory-sticky-header {
    margin: -44px -44px 16px;
  }

  .kasane-logo-sidebar {
    margin-right: 56px;
  }

  .nav-item-qr,
  .nav-item-qr[aria-current="page"] {
    position: fixed;
    top: 18px;
    left: calc(var(--sidebar-width) - 66px);
    z-index: 130;
    display: grid;
    width: 48px;
    min-height: 48px;
    grid-template-columns: 1fr;
    place-items: center;
    border-radius: 50%;
    background: #651868;
    box-shadow: none;
    padding: 0;
    transform: none;
  }

  .nav-item-qr .nav-icon {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: #651868;
    box-shadow: none;
  }

  .nav-item-qr .nav-img {
    width: 24px;
    height: 24px;
  }

  .nav-item-qr > span:last-child {
    display: none;
  }
}

@media (min-width: 1180px) and (hover: hover) and (pointer: fine) {
  .home-dashboard {
    grid-template-areas:
      "topbar topbar"
      "schedule inventory"
      "actions actions";
    grid-template-columns: minmax(460px, 1.55fr) minmax(320px, 0.85fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    max-width: 1180px;
    min-height: calc(100svh - 88px);
    column-gap: 24px;
    row-gap: 20px;
  }

  .home-topbar {
    grid-area: topbar;
  }

  .home-date {
    font-size: 22px;
    line-height: 28px;
  }

  .home-time {
    font-size: 44px;
    line-height: 52px;
  }

  .home-dresser-warning {
    min-height: 40px;
    font-size: 14px;
    padding: 10px 16px;
  }

  .home-schedule-panel {
    grid-area: schedule;
    align-self: stretch;
    grid-template-rows: 44px auto minmax(0, 1fr) 1px auto minmax(0, 1fr);
    height: 100%;
  }

  .home-dashboard > .home-card:not(.home-schedule-panel) {
    grid-area: inventory;
    display: grid;
    grid-template-rows: 44px minmax(0, 1fr);
    align-self: stretch;
    height: 100%;
  }

  .home-card-head,
  .home-dashboard > .panel > .panel-head {
    height: 44px;
    min-height: 44px;
  }

  .home-card-head h2,
  .home-dashboard > .panel > .panel-head h2 {
    font-size: 18px;
    line-height: 24px;
  }

  .schedule-count-badges .schedule-count-pair {
    gap: 8px;
    font-size: 16px;
  }

  .schedule-count-pair b {
    min-height: 22px;
    font-size: 12px;
    padding: 3px 8px;
  }

  .schedule-count-pair em {
    font-size: 18px;
  }

  .timeline-list,
  .week-list {
    min-height: 0;
    align-content: start;
    overflow-y: auto;
    padding: 12px 16px;
  }

  .home-schedule-panel .empty-state {
    min-height: 100%;
    font-size: 14px;
  }

  .timeline-row,
  .week-row {
    min-height: 76px;
    padding: 14px 20px;
  }

  .timeline-row time,
  .week-row > strong,
  .schedule-title-row strong,
  .schedule-title-row span {
    font-size: 16px;
    line-height: 22px;
  }

  .timeline-row p,
  .timeline-side {
    font-size: 14px;
  }

  .schedule-warning-badge,
  .timeline-row .schedule-warning-badge,
  .week-row .schedule-warning-badge {
    font-size: 13px;
    padding: 4px 10px;
  }

  .home-inventory-summary {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: repeat(3, minmax(0, 1fr));
    min-height: 0;
    height: 100%;
    padding: 16px;
  }

  .home-inventory-summary .summary-card {
    min-height: 0;
    border-right: 0;
    border-bottom: 0;
    padding: 16px;
  }

  .home-inventory-summary .summary-card:nth-child(odd) {
    border-right: 1px solid var(--line);
  }

  .home-inventory-summary .summary-card:nth-child(-n + 4) {
    border-bottom: 1px solid var(--line);
  }

  .home-inventory-summary .summary-card span {
    font-size: 16px;
    line-height: 22px;
  }

  .home-inventory-summary .summary-card strong {
    font-size: 36px;
    line-height: 46px;
  }

  .home-action-grid {
    grid-area: actions;
    align-self: end;
    gap: 16px;
  }

  .home-action-button {
    height: 52px;
    min-height: 52px;
    border-radius: 26px;
    font-size: 17px;
  }
}

/* Final SP inventory tuning: keep card height to thumbnail + 10px top/bottom. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {

  .inventory-page .inventory-sticky-header {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    margin-right: 0 !important;
    margin-left: 0 !important;
    padding-right: var(--page-gutter);
    padding-left: var(--page-gutter);
  }

  .inventory-page .inventory-mode-detail .inventory-card {
    position: relative !important;
    grid-template-columns: var(--inventory-detail-columns) !important;
    gap: 10px !important;
    min-height: 118px !important;
    height: 118px !important;
    padding: var(--card-padding-small) !important;
    overflow: hidden !important;
  }

  .inventory-page .inventory-card-main {
    display: flex !important;
    flex-direction: column !important;
    grid-column: 2 !important;
    align-self: flex-start !important;
    min-width: 0 !important;
    padding-top: 0 !important;
    padding-right: 88px !important;
    gap: 4px !important;
  }

  .inventory-page .inventory-card-tags {
    display: flex !important;
    flex-wrap: wrap !important;
    justify-content: flex-start !important;
    align-content: flex-start !important;
    align-items: flex-start !important;
    gap: 4px !important;
    margin: 0 !important;
    padding: 0 !important;
  }

  .inventory-page .inventory-card-tags span {
    flex: 0 0 auto !important;
    min-height: 22px !important;
    height: 22px !important;
    max-height: 22px !important;
    padding: 0 12px !important;
    font-size: 12px !important;
    line-height: 1 !important;
    white-space: nowrap !important;
  }
}

/* Keep the mobile tab bar's material and interaction rules last. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .sidebar {
    --tabbar-surface: rgba(255, 255, 255, 0.84);
    border-top: 1px solid var(--line);
    background: var(--tabbar-surface);
    box-shadow: none;
    padding: 8px 12px max(8px, env(safe-area-inset-bottom));
  }

  @supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .sidebar {
      -webkit-backdrop-filter: blur(20px) saturate(140%);
      backdrop-filter: blur(20px) saturate(140%);
    }
  }

  .nav {
    display: grid;
    min-height: 64px;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    align-items: center;
    justify-items: center;
    gap: 0;
  }

  .nav-item,
  .nav-item[aria-current="page"] {
    display: grid;
    width: 44px;
    min-height: 44px;
    place-items: center;
    border-radius: 50%;
    color: var(--tab-idle);
    transform: none;
    transition: color 160ms ease-out;
  }

  .nav-item:not(.nav-item-qr) .nav-icon {
    transition: transform 100ms ease-out, opacity 100ms ease-out;
  }

  .nav-item:not(.nav-item-qr):active .nav-icon {
    opacity: 0.72;
    transform: scale(0.88);
  }

  .nav-item:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  .nav-item-qr .nav-icon {
    width: 80px;
    height: 80px;
    background: var(--accent);
    box-shadow: none;
    transition: transform 100ms ease-out, box-shadow 160ms ease-out;
  }

  .nav-item-qr:active .nav-icon {
    box-shadow: none;
    transform: scale(0.94);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav-item,
  .nav-item .nav-icon {
    transition: none !important;
  }
}

@media (prefers-reduced-transparency: reduce) {
  @media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
    .sidebar {
      background: var(--paper);
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
  }
}

/* Final mobile tab bar treatment. This stays after legacy mobile rules. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .sidebar {
    min-height: 88px;
    border-top: 1px solid var(--line);
    border-bottom: 0;
    background: rgba(255, 255, 255, 0.86);
    box-shadow: none;
    padding: 8px 12px max(8px, env(safe-area-inset-bottom));
  }

  .nav {
    display: grid;
    min-height: 64px;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    align-items: center;
    justify-items: center;
    gap: 0;
  }

  .nav-item,
  .nav-item[aria-current="page"] {
    width: 48px;
    min-height: 48px;
    border-radius: 14px;
    color: var(--tab-idle);
    transform: none;
    transition: color 160ms ease-out, background-color 160ms ease-out;
  }

  .nav-img {
    width: 30px;
    height: 30px;
  }
}

/* ANA-inspired mobile navigation: one floating material bar, with equal destinations.
   --bottom-tabbar-height is intentionally not set here: a later, identically
   scoped @media (max-width: 767.98px) block owns that token (88px) so there is
   exactly one place to look for the effective mobile tab-bar height. A 116px
   override used to sit here too, but it was always shadowed by that later
   block at the same breakpoint and had no effect on any rendered layout. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .sidebar {
    min-height: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
    padding: 0 20px max(12px, env(safe-area-inset-bottom));
    pointer-events: none;
  }

  .nav {
    width: 100%;
    min-height: 80px;
    padding: 10px;
    border: 1px solid rgba(255, 255, 255, 0.76);
    border-radius: 38px;
    background: rgba(255, 255, 255, 0.8);
    box-shadow: none;
    -webkit-backdrop-filter: blur(22px) saturate(145%);
    backdrop-filter: blur(22px) saturate(145%);
    pointer-events: auto;
  }

  .nav-item,
  .nav-item[aria-current="page"],
  .nav-item-qr,
  .nav-item-qr[aria-current="page"] {
    width: 100%;
    min-height: 62px;
    padding: 0;
    border-radius: 31px;
    background: transparent;
    color: var(--muted);
    transform: none;
  }

  .nav-item[aria-current="page"]:not(.nav-item-qr),
  .nav-item-qr[aria-current="page"] {
    background: rgba(101, 24, 104, 0.1);
    color: var(--accent);
  }

  .nav-item > span:last-child {
    display: block;
    font-size: var(--bottom-nav-label-size);
    font-weight: var(--bottom-nav-label-weight);
    line-height: 1.3;
  }

  .nav-img {
    width: 26px;
    height: 26px;
  }

  .nav-item-qr .nav-icon {
    position: absolute;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: none;
    transform: translateY(-20px);
  }

  .nav-item-qr > span:last-child {
    display: none;
  }

  .nav-item-qr:active .nav-icon {
    transform: translateY(-20px) scale(0.94);
  }

  .nav-item:active {
    transform: scale(0.96);
  }
}

@media (max-width: 767.98px) and (prefers-reduced-transparency: reduce), (hover: none) and (pointer: coarse) and (prefers-reduced-transparency: reduce) {
  .nav {
    background: var(--paper);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* Keep mobile lists on the same settings rhythm after screen-specific styles. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .page-title h1,
  .item-editor-header h1,
  .page-header h1 {
    font-size: 16px;
    font-weight: 700;
  }

  .timeline-row,
  .week-row,
  .ledger-phase-stack .calendar-row {
    min-height: var(--settings-row-height);
    border-radius: var(--radius);
    padding: 10px var(--settings-list-inset);
    font-size: 14px;
    font-weight: 500;
  }

  .ledger-phase-stack .management-settings-group > h2 {
    padding-inline: var(--settings-list-inset);
    font-size: 15px;
    font-weight: 500;
  }

  .ledger-phase-stack .management-settings-group > .panel {
    margin-top: 0;
    border-radius: var(--radius);
  }

  /* 予約一覧 / カレンダー: the switch stands a section's gap above what it
     shows, the same rhythm as the space above it (owner, 2026-09-29). */
  .ledger-phase-stack .segmented-pills--even {
    margin-bottom: var(--settings-section-gap);
  }

  .ledger-phase-stack .reservation-table th,
  .ledger-phase-stack .reservation-table td {
    padding: 10px var(--settings-list-inset);
    font-size: 14px;
  }

  .ledger-phase-stack .reservation-table th {
    font-weight: 600;
  }

  .ledger-phase-stack .reservation-table td,
  .ledger-phase-stack .calendar-row {
    font-size: 14px;
    font-weight: 500;
  }

  .ledger-phase-stack .calendar-list {
    gap: var(--settings-group-title-gap);
    padding: 10px var(--settings-list-inset);
  }

  .timeline-row time,
  .week-row > strong,
  .schedule-title-row strong,
  .schedule-title-row span {
    font-size: 14px;
    font-weight: 500;
  }

  .timeline-row p,
  .timeline-side {
    font-size: 12px;
    font-weight: 400;
  }

}

/* Shared content elevations and compact reservation table. */
.main .panel,
.main .card {
  box-shadow: none;
}

.reservation-list-panel {
  overflow: hidden !important;
}

.reservation-table-scroll {
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  /* none, not contain. contain only stops a scroll from chaining to the
     document; the strip itself is still free to rubber-band under a finger,
     on both axes. This is the app's only horizontally scrollable region, so
     it was also the only place a sideways drag could bounce anything (P058). */
  overscroll-behavior: none;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.reservation-table-scroll::-webkit-scrollbar {
  display: none;
}

.reservation-table {
  min-width: var(--reservation-table-min-width);
}

.reservation-table th,
.reservation-table td {
  padding: 10px var(--reservation-table-cell-pad);
  font-size: 13px;
  line-height: 1.4;
  white-space: nowrap;
}

.reservation-table th:nth-child(1) { width: 124px; }
.reservation-table th:nth-child(2) { width: 84px; }
.reservation-table th:nth-child(3) { width: 92px; }
.reservation-table th:nth-child(4) { width: 72px; }
.reservation-table th:nth-child(5) { width: 132px; }
.reservation-table th:nth-child(6) { width: 72px; }

/* Keep every create action in one predictable place: above the mobile tab bar. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .fab-cluster,
  .inventory-fab-cluster,
  .ledger-fab-cluster {
    right: var(--fab-edge) !important;
    bottom: calc(var(--bottom-tabbar-height) + var(--fab-gap) + env(safe-area-inset-bottom)) !important;
    left: auto !important;
    justify-items: end;
  }

  .fab-button,
  .inventory-fab-cluster .fab-button,
  .ledger-fab-cluster .fab-button,
  .customer-create-fab,
  .maintenance-register-fab,
  .ledger-operation-fab {
    position: fixed !important;
    top: auto !important;
    right: var(--fab-edge) !important;
    bottom: calc(var(--bottom-tabbar-height) + var(--fab-gap) + env(safe-area-inset-bottom)) !important;
    left: auto !important;
    width: var(--fab-size);
    height: var(--fab-size);
  }

  .fab-menu {
    justify-self: end;
  }
}

@media (min-width: 768px) and (hover: hover) and (pointer: fine) {
  .fab-cluster,
  .inventory-fab-cluster,
  .ledger-fab-cluster {
    right: 24px !important;
    bottom: 24px !important;
    left: auto !important;
    justify-items: end;
  }

  .fab-button,
  .inventory-fab-cluster .fab-button,
  .ledger-fab-cluster .fab-button {
    right: 24px !important;
    bottom: 24px !important;
    left: auto !important;
  }

  .fab-menu {
    justify-self: end;
  }
}

/* Mobile rhythm: keep page titles, card edges, and inventory content on one grid. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .home-schedule-panel > .home-schedule-divider {
    margin: var(--schedule-divider-gap) 10px;
  }

  .page-transition > .page-title:not(.ledger-page-title) {
    margin-bottom: var(--page-content-gap);
  }

  .page-transition > .topbar {
    gap: 0;
    margin-bottom: var(--page-content-gap);
  }

  .page-transition > .topbar > .page-title {
    margin-bottom: 0;
  }

  .page-transition > .ledger-page-title {
    margin-bottom: 0;
  }

  .inventory-page .inventory-title-row .head-count {
    display: none;
  }

  .inventory-page .inventory-result-count {
    padding: 16px var(--mobile-page-gutter) !important;
  }

  .inventory-page .inventory-panel.panel {
    padding-right: var(--mobile-page-gutter) !important;
    padding-left: var(--mobile-page-gutter) !important;
  }

  .ledger-phase-stack .tab-content > .panel {
    box-shadow: none;
  }

  .ledger-phase-stack .panel-head h2,
  .ledger-phase-stack .panel h2 {
    font-size: 14px;
    line-height: 24px;
  }

  .ledger-phase-stack .panel .head-count,
  .ledger-phase-stack .panel .table th {
    font-size: 12px;
  }

  .ledger-phase-stack .panel .table td,
  .ledger-phase-stack .calendar-row {
    font-size: 14px;
    font-weight: 500;
  }

  .settings-row {
    min-height: 52px;
    font-size: 15px;
  }

  .settings-row-icon {
    width: 28px;
    height: 28px;
    font-size: 16px;
  }
}

/* Compact glass navigation: content continues underneath the floating control. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  :root {
    --bottom-tabbar-height: 88px;
  }

  /* Align the inventory title baseline with the ledger and management titles. */
  .inventory-page .inventory-sticky-header {
    justify-content: flex-start;
    /* This band paints the very top of the screen, so it reserves the
       status-bar strip itself, the way .management-screen-header does. */
    min-height: calc(158px + env(safe-area-inset-top));
    padding-top: calc(16px + env(safe-area-inset-top));
  }

  /* The ledger centres its title in a taller band, which put it 4px below the
     inventory's (owner, 2026-10-08: 「在庫と台帳のタイトルの位置ずれ」). The
     band's height stays; only the title moves, until both screens share one
     header component. */
  .ledger-page-title h1 {
    position: relative;
    top: -4px;
  }

  /* Only the floating pill is glass. The full-width holder kept an older
     20px blur with no background, which blurred a band of the screen from
     the pill's top edge down (owner 2026-10-15; Apple Music shows content
     around its tab bar unblurred). */
  .sidebar {
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    padding: 0 12px max(20px, env(safe-area-inset-bottom));
  }

  .nav {
    min-height: 60px;
    height: 60px;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    align-items: stretch;
    justify-items: stretch;
    gap: 0;
    padding: 4px;
    border: 1px solid color-mix(in srgb, var(--paper) 72%, transparent);
    border-radius: 32px;
    background: color-mix(in srgb, var(--paper) 52%, transparent);
    box-shadow: none;
    -webkit-backdrop-filter: blur(24px) saturate(145%);
    backdrop-filter: blur(24px) saturate(145%);
  }

  .nav-item,
  .nav-item[aria-current="page"] {
    width: 100%;
    min-height: 0;
    height: 100%;
    padding: 1px 0;
    border-radius: 26px;
  }

  .nav-item > span:last-child {
    font-size: 9px;
  }

  .nav-icon,
  .nav-img {
    width: 24px;
    height: 24px;
  }

  .nav-item-qr .nav-icon {
    width: 68px;
    height: 68px;
    transform: translateY(-17px);
  }

  .nav-item-qr .nav-img {
    width: 32px;
    height: 32px;
  }

  .nav-item-qr:active .nav-icon {
    transform: translateY(-17px) scale(0.94);
  }

  .main {
    padding-bottom: 16px !important;
  }

  .main:has(.inventory-page),
.main:has(.inventory-sticky-header) {
    padding-bottom: 0 !important;
  }

  /* Home uses the shared page content width without a screen-specific offset. */
  .home-dashboard {
    width: 100%;
    max-width: none;
    margin-right: 0;
    margin-left: 0;
  }
}

/* The selected tab's tint slides from the tab left to the one opened
   (2026-09-28): one shape behind the icons, measured and moved by
   AppNavigation, which also places it at once where it must not slide
   (first placement, resizing, reduced motion). Until it is placed, the
   selected tab draws its own. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .nav.is-sliding > .nav-pill {
    display: block;
    top: 0;
    bottom: auto;
    left: 0;
    z-index: -1;
    border-radius: 26px;
    background: rgba(101, 24, 104, 0.1);
    transition: transform 300ms cubic-bezier(0.2, 0.8, 0.2, 1), width 300ms cubic-bezier(0.2, 0.8, 0.2, 1);
  }

  .nav.is-sliding > .nav-item[aria-current="page"] {
    background: transparent;
  }
}

/* QR is a primary action, not a selected navigation tab. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .nav-item-qr[aria-current="page"] {
    background: transparent;
  }

  .nav-item-qr .nav-icon {
    border-radius: 50%;
    background: var(--accent);
    box-shadow: none;
  }
}

@media (max-width: 767.98px) and (prefers-reduced-transparency: reduce), (hover: none) and (pointer: coarse) and (prefers-reduced-transparency: reduce) {
  .nav {
    background: var(--paper);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* White application surfaces are separated from the background by depth, not a gray outline. */
.panel:not(.inventory-panel):not(.inventory-scan-panel),
.reservation-registration-scroll .reservation-step-body,
.management-subpage .settings-list,
.customer-directory-list,
.customer-settings-list,
.customer-next-section,
.history-box,
.employee-directory-list,
.audit-filter-surface,
.audit-log-list,
.security-recovery-list,
.sync-device-panel .management-card-list,
.csv-feature-group > .csv-box {
  border: 0 !important;
  /* Settings-style white groups sit directly on the app surface, like iOS
     Settings, separated by depth rather than a border. --bg and --paper are
     both white, so a real shadow (not none) is required for the edge to
     read against the page. */
  box-shadow: none;
}

/* Shared type scale: every screen uses the same hierarchy rather than
   redefining headings and settings rows per destination.
   Weights are calibrated against real iOS Settings on-device (not this
   sandbox, which has no Hiragino/San Francisco): a standard iOS nav title
   is Semibold, a grouped-list row label is plain Regular -- iOS does not
   bold its row labels, it separates label from value by color, not
   weight. The previous 800/700/600/500 scale was tuned before the
   -apple-system font-stack bug (see the app-system-font fix) was found,
   compensating for what was actually a broken/legacy-font fallback
   rendering everything thin; once the real system font loads, those
   values read noticeably heavier than genuine iOS. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  /* The ledger uses the inventory header treatment; the scrollable body begins
     below it. Only the ledger's own band is the accent: .shell, .main and
     .page-transition span the viewport, so they are what iOS paints behind the
     safe area and they stay on the app canvas. They used to be listed here
     too, and were then forced back to var(--bg) by two later !important rules
     -- a contradiction that read as a coloured strip disagreeing with the
     content under it, and that the safe-area check could not see. */
  .ledger-phase-stack,
  .ledger-page-title {
    background: var(--accent);
  }

  .ledger-page-title h1 {
    color: var(--paper);
  }

  .ledger-phase-stack .tab-content {
    background: var(--bg);
    padding: var(--settings-section-gap) var(--page-gutter) calc(var(--bottom-tabbar-height) + 32px + env(safe-area-inset-bottom)) !important;
  }

  /* Keep the complete ledger header on the accent surface.  The generic page
     title surface is intentionally overridden here because this destination
     uses the inventory-style header. */
  .main:has(.ledger-phase-stack) .page-transition > .ledger-page-title {
    background: var(--accent) !important;
  }

  .main:has(.ledger-phase-stack) .page-transition > .ledger-page-title h1 {
    color: var(--paper) !important;
  }

  /* Management detail destinations do not render the bottom tab bar. */
  .management-screen {
    bottom: 0;
  }

  .management-screen-scroll {
    background: var(--bg);
    /* --page-content-gap on top of the card inset so the last card stops
       short of the bottom edge instead of ending flush against it. */
    padding-bottom: calc(var(--settings-list-inset) + var(--page-content-gap) + env(safe-area-inset-bottom));
  }

  .page-title h1,
  .item-editor-header h1,
  .page-header h1,
  .management-screen-header h1,
  .inventory-title-row h1,
  .inventory-scan-header h2 {
    font-size: var(--ui-page-title-size);
    font-weight: var(--ui-page-title-weight);
    line-height: var(--ui-page-title-line-height);
  }

  .home-card-head h2,
  .home-dashboard > .panel > .panel-head h2,
  .schedule-section-head h2,
  .settings-menu-group > h2,
  .management-settings-group > h2,
  .store-settings-section-title > h2,
  .customer-section-heading > h2,
  .customer-detail-section > h2,
  .history-section > h2,
  .customer-form-screen .form-group-section > h2,
  .employee-directory-heading > h2,
  .employee-editor-heading > h2,
  .audit-panel > h2,
  .security-recovery-group > h2,
  .sync-device-panel > h2,
  .sync-device-notice > h2,
  .csv-feature-group > h2,
  .ledger-phase-stack .management-settings-group > h2,
  .ledger-phase-stack .panel-head h2 {
    font-size: var(--ui-section-title-size);
    font-weight: var(--ui-section-title-weight);
    line-height: var(--ui-section-title-line-height);
  }

  .management-subpage .settings-row,
.customer-directory-row,
.customer-next-row,
.customer-setting-row,
.employee-directory-row,
.security-recovery-row,
.sync-device-panel .management-card,
.inventory-mode-detail .inventory-card-title span {
    font-size: var(--ui-row-label-size);
    font-weight: var(--ui-row-label-weight);
    line-height: var(--ui-row-label-line-height);
  }

  .settings-row-value,
  .customer-setting-row > strong,
  .store-settings-read-row > strong,
  .store-settings-navigation-row > strong,
  .employee-directory-row .employee-status,
  .employee-directory-row .employee-directory-meta,
  .audit-log-row time,
  .audit-log-row small,
  .security-recovery-row > span:last-child,
  .sync-device-panel .management-card small,
  .inventory-mode-detail .inventory-card-title strong,
  .inventory-result-count,
  .timeline-row p,
  .timeline-side {
    font-size: var(--ui-supporting-text-size);
    font-weight: var(--ui-supporting-text-weight);
  }

  /* Home's two section bars take the height of the rows inside the card
     (今日・今週, 36px) and of the inventory header's controls; at 48px, like
     the buttons below, they spent space the schedule needed (2026-09-27). */
  .home-card-head {
    height: var(--home-card-head-height);
    min-height: var(--home-card-head-height);
  }

  .home-action-button {
    font-size: var(--ui-section-title-size);
    font-weight: var(--ui-section-title-weight);
    line-height: var(--ui-section-title-line-height);
  }

  .ledger-phase-stack .management-settings-group > h2 {
    padding-inline: 0;
  }

  .ledger-phase-stack .reservation-table thead th {
    background: var(--accent);
    color: var(--paper);
  }

  /* Settings, management, and history use the same section-heading hierarchy
     as the customer directory.  Only the page content changes by destination. */
  .settings-menu-group > h2,
  .store-settings-section-title > h2,
  .management-subpage .panel-head h2 {
    font-size: var(--ui-section-title-size);
    font-weight: var(--ui-section-title-weight);
    line-height: var(--ui-section-title-line-height);
  }

  .management-subpage .settings-row {
    font-size: var(--ui-row-label-size);
    font-weight: var(--ui-row-label-weight);
    line-height: var(--ui-row-label-line-height);
  }

  .management-screen-scroll {
    /* The fixed management header already provides the shared title rhythm.
       Adding the page gap here made every first section start too low. */
    padding-top: 0;
  }

  /* List headings start at the same edge as their cards; the shared content
     gutter already supplies the page inset.  The heading wrappers themselves
     take their inset from the grey-heading contract later in this file. */
  .audit-panel > h2,
  .security-recovery-group > h2,
  .sync-device-panel > h2,
  .sync-device-notice > h2,
  .csv-feature-group > h2 {
    padding-inline: 0;
  }

  /* Ease from app content into the floating tab bar without an abrupt cut. */
  .sidebar {
    isolation: isolate;
    overflow: visible;
  }

  .sidebar::before {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 0;
    height: calc(var(--bottom-tabbar-height) + 72px + env(safe-area-inset-bottom));
    background: linear-gradient(to bottom, transparent 0%, color-mix(in srgb, var(--bg) 82%, transparent) 100%);
    content: "";
    pointer-events: none;
  }

  .sidebar > * {
    position: relative;
    z-index: 1;
  }

  /* Every tab-bar screen reserves its controls' footprint at the scroll end. */
  .main {
    padding-bottom: calc(var(--bottom-tabbar-height) + 24px + env(safe-area-inset-bottom)) !important;
  }

  .inventory-panel.panel,
  .ledger-phase-stack .tab-content {
    padding-bottom: calc(var(--bottom-tabbar-height) + 24px + env(safe-area-inset-bottom)) !important;
  }

  /* Reusable settings-style editor list.  Item editing now follows the same
     one-row, divider-led hierarchy as the other detailed editors. */
  .item-editor-panel {
    overflow: hidden;
    padding: 0;
  }

  .item-editor-panel .item-form {
    display: block;
    padding: 0;
  }

  .item-editor-panel .item-form > label:not(.full-span),
  .item-editor-panel .item-form > .tag-control {
    display: grid;
    grid-template-columns: var(--settings-label-value-columns);
    align-items: center;
    gap: 12px;
    min-height: var(--settings-row-height);
    margin: 0;
    padding: 8px var(--settings-list-inset);
    border-bottom: var(--settings-divider-width) solid var(--settings-divider-color);
    color: var(--settings-label-color);
    font-size: var(--ui-row-label-size);
    font-weight: 400;
  }

  .item-editor-panel .item-form > label:not(.full-span) > input,
  .item-editor-panel .item-form > label:not(.full-span) > select,
  .item-editor-panel .item-form > .tag-control > .tag-box {
    width: 100%;
    min-height: 40px;
    margin: 0;
    border: 0 !important;
    background: transparent;
    box-shadow: none;
    color: var(--settings-value-color);
    text-align: right;
  }

  .item-editor-panel .item-form > .tag-control > .tag-box {
    grid-column: 2;
  }

  .item-editor-panel .item-form > .tag-control > .tag-suggestions {
    grid-column: 2;
  }

  .item-editor-panel .item-form .item-identity-row {
    align-items: center;
    margin: 0;
    padding: var(--settings-list-inset);
    border-bottom: var(--settings-divider-width) solid var(--settings-divider-color);
  }

  .item-editor-panel .item-form .item-identity-row > label {
    display: grid;
    gap: 6px;
    color: var(--settings-label-color);
    font-size: var(--ui-row-label-size);
  }

  .item-editor-panel .item-form .item-identity-row input {
    min-height: 40px;
    margin: 0;
    border: 0 !important;
    background: transparent;
    box-shadow: none;
    color: var(--settings-value-color);
  }

  .item-editor-panel .item-form > label.full-span {
    display: grid;
    gap: 8px;
    min-height: var(--settings-row-height);
    margin: 0;
    padding: 12px var(--settings-list-inset);
    border-bottom: var(--settings-divider-width) solid var(--settings-divider-color);
    color: var(--settings-label-color);
    font-size: var(--ui-row-label-size);
    font-weight: 400;
  }

  .item-editor-panel .item-form > label.full-span > textarea,
  .item-editor-panel .item-form > label.full-span > input {
    margin: 0;
    border: 0 !important;
    background: transparent;
    box-shadow: none;
  }

  .item-editor-panel .item-form .form-action {
    width: calc(100% - (var(--settings-list-inset) * 2));
    margin: var(--settings-section-gap) var(--settings-list-inset);
  }

  .inventory-sort-control {
    transition: transform 160ms ease, box-shadow 160ms ease;
  }

  .inventory-sort-control > span {
    color: var(--ink);
    font-size: 14px;
    font-weight: 700;
  }

  .inventory-sort-control select {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    cursor: pointer;
    opacity: 0;
  }

  .inventory-sort-control:active,
  .inventory-sort-control:has(select:active) {
    transform: scale(0.97);
  }

  /* The direct actions and card bars share the 48px touch height. */
  .home-card-head,
  .home-dashboard > .panel > .panel-head {
    min-height: var(--home-card-head-height);
    height: var(--home-card-head-height);
  }

  .home-action-button {
    min-height: 48px;
    height: 48px;
  }

  .home-action-button {
    border-radius: 24px;
  }

  /* Keep the day/week labels mathematically centered while their counts stay
     aligned to the trailing edge. */
  .home-schedule-panel .schedule-count-badges {
    grid-column: 3;
    justify-self: end;
  }

  /* A long multi-stop fade prevents the floating navigation region from
     reading as a hard horizontal edge above the bar. */
  .sidebar::before {
    height: calc(var(--bottom-tabbar-height) + 144px + env(safe-area-inset-bottom));
    background: linear-gradient(
      to bottom,
      rgb(253 247 253 / 0%) 0%,
      rgb(253 247 253 / 8%) 28%,
      rgb(253 247 253 / 32%) 56%,
      rgb(253 247 253 / 68%) 82%,
      var(--bg) 100%
    );
  }

  /* Reservation tables use depth from their parent card, not gray rules at
     the purple-header/white-body transition or after their final row. */
  .ledger-phase-stack .reservation-table thead th,
  .ledger-phase-stack .reservation-table tbody tr:last-child td {
    border-bottom: 0 !important;
  }

  /* The page gutter is already supplied by each screen container.  Section
     headings must not add a second inset before their card/list begins. */
  .settings-menu-group > h2,
  .management-settings-group > h2,
  .store-settings-group > h2,
  .customer-section-heading > h2,
  .customer-detail-section > h2,
  .history-section > h2,
  .customer-form-screen .form-group-section > h2,
  .employee-directory-heading > h2,
  .employee-editor-heading > h2,
  .audit-panel > h2,
  .security-recovery-group > h2,
  .sync-device-panel > h2,
  .sync-device-notice > h2,
  .csv-feature-group > h2 {
    padding-inline: 0;
  }

  /* Maintenance is a settings destination: title rhythm, labels and fields
     follow the same single-column list structure as the other editors. */
  .page-transition:has(.maintenance-stack) {
    /* Match other back-button pages: one shared title-to-content gap. */
    column-gap: 0;
    row-gap: var(--page-content-gap);
  }

  .maintenance-stack {
    gap: var(--settings-section-gap);
  }

  .maintenance-stack .management-settings-group {
    gap: var(--settings-group-title-gap);
  }

  .maintenance-stack .management-settings-group > h2 {
    padding-inline: 0;
  }

  .maintenance-stack .maintenance-list {
    gap: 0;
    padding: 0;
  }

  .maintenance-stack .maintenance-list > .empty-state {
    margin: 0;
    border: 0 !important;
    border-image: none !important;
    box-shadow: none;
    background: transparent;
  }

  .maintenance-stack .maintenance-card {
    border: 0;
    border-bottom: var(--settings-divider-width) solid var(--settings-divider-color);
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    padding: var(--settings-list-inset);
  }

  .maintenance-stack .maintenance-card.is-active {
    border-color: var(--settings-divider-color);
    background: transparent;
  }

  .maintenance-stack .maintenance-card:last-of-type {
    border-bottom: 0;
  }

  .maintenance-register-panel {
    width: 100%;
    margin: 0;
    overflow: hidden;
    padding: 0;
  }

  .maintenance-register-panel .item-form > label:not(.full-span) {
    display: grid;
    grid-template-columns: var(--settings-label-value-columns);
    align-items: center;
    gap: 12px;
    min-height: var(--settings-row-height);
    margin: 0;
    padding: 8px var(--settings-list-inset);
    border-bottom: var(--settings-divider-width) solid var(--settings-divider-color);
    color: var(--settings-label-color);
    font-size: var(--ui-row-label-size);
    font-weight: 400;
  }

  .maintenance-register-panel .item-form > label:not(.full-span) > select,
  .maintenance-register-panel .item-form > label:not(.full-span) > input {
    width: 100%;
    min-height: 40px;
    margin: 0;
    border: 0 !important;
    background: transparent;
    box-shadow: none;
    color: var(--settings-value-color);
    text-align: right;
  }

  .maintenance-register-panel .item-form > label.full-span {
    display: grid;
    gap: 8px;
    margin: 0;
    padding: 12px var(--settings-list-inset);
    border-bottom: var(--settings-divider-width) solid var(--settings-divider-color);
    color: var(--settings-label-color);
    font-size: var(--ui-row-label-size);
    font-weight: 400;
  }

  .maintenance-register-panel .item-form .form-action {
    width: calc(100% - (var(--settings-list-inset) * 2));
    min-width: 0;
    min-height: 48px;
    justify-self: stretch;
    margin: var(--settings-section-gap) var(--settings-list-inset);
  }

  /* The edit-page grid must not stretch the shared circular back control. */
  .page-transition:has(> .back-button + .back-button-spacer + .page-title) > .back-button {
    width: 44px;
    min-width: 44px;
    height: 44px;
    min-height: 44px;
    aspect-ratio: 1;
  }

  /* Preserve scrolling while keeping native rails out of the app surface. */
  html,
  body,
  .main,
  .page-transition,
  .ledger-phase-stack .tab-content,
  .management-screen-scroll,
  .reservation-registration-scroll .reservation-form-scroll-content,
  .inventory-panel.panel,
  .inventory-scan-panel .scan-body,
  .inventory-scan-panel .inventory-scan-content {
    -ms-overflow-style: none;
    scrollbar-width: none;
  }

  html::-webkit-scrollbar,
  body::-webkit-scrollbar,
  .main::-webkit-scrollbar,
  .page-transition::-webkit-scrollbar,
  .ledger-phase-stack .tab-content::-webkit-scrollbar,
  .management-screen-scroll::-webkit-scrollbar,
  .reservation-registration-scroll .reservation-form-scroll-content::-webkit-scrollbar,
  .inventory-panel.panel::-webkit-scrollbar,
  .inventory-scan-panel .scan-body::-webkit-scrollbar,
  .inventory-scan-panel .inventory-scan-content::-webkit-scrollbar {
    display: none;
    width: 0;
    height: 0;
  }

  /* Reservation details use the same compact rows as settings and customer
     details instead of the older, taller 64px cards. */
  .reservation-detail-section > h2,
  .reservation-history-section > h2 {
    padding-inline: 0;
  }

  .reservation-setting-row {
    min-height: var(--settings-row-height);
    padding-inline: var(--settings-list-inset);
  }

  .customer-field-editor {
    overflow: hidden;
    padding: 0;
  }

  .customer-field-editor form {
    display: grid;
    gap: 0;
  }

  .customer-field-editor label {
    display: grid;
    grid-template-columns: var(--settings-label-value-columns);
    align-items: center;
    gap: 12px;
    min-height: var(--settings-row-height);
    padding: 8px var(--settings-list-inset);
    color: var(--settings-label-color);
    font-size: var(--ui-row-label-size);
    font-weight: 400;
  }

  .customer-field-editor input:not(.value-pill),
  .customer-field-editor select:not(.value-pill),
  .customer-field-editor textarea {
    min-height: 40px;
    border: 0 !important;
    background: transparent;
    box-shadow: none;
    text-align: right;
  }

  .customer-field-editor .form-action {
    width: calc(100% - (var(--settings-list-inset) * 2));
    min-height: 48px;
    margin: var(--settings-section-gap) var(--settings-list-inset);
  }

  /* The dashboard itself stays fixed on mobile; only the schedule card owns
     a scroll region, so inventory and the two direct actions remain visible. */
  .shell:has(.home-dashboard),
  .main:has(.home-dashboard),
  .main:has(.home-dashboard) .page-transition {
    height: 100dvh;
    min-height: 0;
    overflow: hidden;
  }

  .main:has(.home-dashboard) {
    padding-bottom: 0 !important;
  }

  .home-dashboard {
    /* Fits the viewport exactly, so it has to give up both insets, not only
       the bottom one: .main now reserves the status-bar strip above it. */
    height: calc(
      100dvh - var(--bottom-tabbar-height) - env(safe-area-inset-top) - env(safe-area-inset-bottom)
    );
    min-height: 0;
    grid-template-rows: auto minmax(150px, 1fr) auto auto;
    align-content: stretch;
    /* auto, not hidden. The schedule panel is deliberately pinned to a
       fixed three-row viewport further down this file, so it cannot give
       up height; once the status-bar strip is reserved above (P058), a
       notched iPhone in Safari is ~59px short and the stats card was the
       one being cut off. Scrolling those last pixels beats clipping them,
       and where the inset is 0 -- every desktop browser, and the installed
       PWA, whose status-bar style keeps content below the bar -- the
       dashboard still fits exactly and no scroll appears. */
    overflow-y: auto;
    overscroll-behavior: none;
    padding-bottom: 12px;
  }

  .home-schedule-panel {
    position: relative;
    display: grid;
    grid-template-rows: var(--home-card-head-height) minmax(0, 1fr);
    min-height: 0;
  }

  .home-schedule-scroll {
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: none;
    scrollbar-width: none;
  }

  .home-schedule-scroll::-webkit-scrollbar {
    display: none;
  }

  .home-schedule-more {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    margin: 0;
    background: linear-gradient(to bottom, rgb(255 255 255 / 0%), rgb(255 255 255 / 94%) 62%);
    color: var(--accent);
    font-size: 11px;
    font-weight: 600;
    line-height: 24px;
    pointer-events: none;
    text-align: center;
  }

  .home-dresser-warning {
    background: var(--danger);
    color: var(--paper);
  }

  .home-schedule-panel .schedule-empty-week {
    font-size: 15px;
    font-weight: 500;
  }

  /* The notice screen is nested in Home, so cancel that parent gutter before
     applying the same shared 18px edge as every other screen. */
  .notice-screen {
    margin-right: calc(-1 * var(--mobile-page-gutter));
    margin-left: calc(-1 * var(--mobile-page-gutter));
  }

  .notice-screen .management-settings-group {
    padding-right: var(--mobile-page-gutter);
    padding-left: var(--mobile-page-gutter);
  }

  /* お知らせ is drawn inside .main, which already starts
     --mobile-main-top-gap under the status bar, so its title sat 10pt and its
     card 18pt higher than every routed screen (owner, 2026-09-29). Put the
     title row at the routed screens' --management-header-top-gap, and the
     card the routed screens' 20pt under it (the grid gives 12). */
  .notice-screen .management-screen-header {
    padding-top: calc(var(--management-header-top-gap) - var(--mobile-main-top-gap));
    margin-bottom: 8px;
  }

  /* Field editors intentionally keep a subtle edge: an editable value must
     not read like static text in a settings-style row. */
  .customer-field-editor input:where(:not(.value-pill, .value-pill-control)),
  .customer-field-editor select:where(:not(.value-pill, .value-pill-control)),
  .customer-field-editor textarea,
  .reservation-field-editor input:where(:not(.value-pill, .value-pill-control)),
  .reservation-field-editor select:where(:not(.value-pill, .value-pill-control)),
  .reservation-field-editor textarea {
    border: 1px solid var(--line) !important;
    border-radius: 10px;
    background: var(--paper) !important;
    box-shadow: none;
  }

  .customer-field-editor input:where(:not(.value-pill, .value-pill-control)),
  .customer-field-editor select:where(:not(.value-pill, .value-pill-control)),
  .reservation-field-editor input:where(:not(.value-pill, .value-pill-control)),
  .reservation-field-editor select:where(:not(.value-pill, .value-pill-control)) {
    padding-inline: 12px;
  }

  /* The item slots and the price box are white list cards like the rest of
     the form: the grey 1px border and 10px corner were the retired design and
     drew a line along the card's bottom edge (card-gaps 2026-10-15). */
  .reservation-form-panel .reservation-item-rows {
    border: 0;
    border-radius: var(--settings-list-radius);
    background: var(--settings-list-surface);
    box-shadow: none;
  }

  .reservation-form-panel .reservation-item-rows > * {
    padding-inline: var(--settings-list-inset);
  }

  /* The slots and the ways to add an item are two boxes; the field's own gap
     (6px) plus this is the form's 16px between fields. */
  .reservation-form-panel .reservation-item-rows + .reservation-item-rows {
    margin-top: 10px;
  }

  .customer-field-editor textarea {
    grid-column: 2;
    min-height: 104px;
    padding: 12px;
    resize: vertical;
  }

  .reservation-field-editor {
    overflow: hidden;
    padding: 0;
  }

  .reservation-field-editor form {
    display: grid;
    gap: 0;
  }

  .reservation-field-editor label {
    display: grid;
    grid-template-columns: var(--settings-label-value-columns);
    align-items: center;
    gap: 12px;
    min-height: var(--settings-row-height);
    padding: 8px var(--settings-list-inset);
    color: var(--settings-label-color);
    font-size: var(--ui-row-label-size);
    font-weight: 400;
  }

  .reservation-field-editor textarea,
  .reservation-field-editor select[multiple] {
    min-height: 112px;
    padding: 10px 12px;
  }

  .reservation-field-editor .form-action {
    width: calc(100% - (var(--settings-list-inset) * 2));
    min-height: 48px;
    margin: var(--settings-section-gap) var(--settings-list-inset);
  }

  /* The dashboard is a fixed screen.  Today and this week each own a small,
     independent list viewport so one busy section cannot push the other
     controls beneath the QR navigation. */
  .home-dashboard {
    gap: 8px;
    overflow: visible;
    padding-bottom: 4px;
  }

  .home-schedule-sections {
    display: grid;
    min-height: 0;
    grid-template-rows: minmax(0, 1fr) 1px minmax(0, 1fr);
  }

  .home-schedule-section {
    position: relative;
    display: grid;
    min-height: 0;
    grid-template-rows: auto minmax(0, 1fr);
  }

  .home-schedule-panel .timeline-list,
  .home-schedule-panel .week-list {
    gap: 6px;
    padding: 0 10px 8px;
  }

  .home-schedule-section .home-schedule-more {
    bottom: 0;
    background: var(--paper);
  }

  /* The cells' dividers run to the card's padding, so the padding is the
     lines' inset. It was 6px above and below against 10px at the sides, and
     the vertical lines nearly touched the card's header and bottom edge
     (2026-09-27); one 10px inset on every side, the same edge the schedule
     card's divider keeps. */
  .home-inventory-summary {
    min-height: 0;
    padding: 10px;
  }

  /* No inset of their own: the card's 10px inset gives the space above the
     top row and below the bottom row, and the same 10px on each side of the
     divider gives both rows one layout (2026-09-27). The 4px each cell added
     on top read as too loose on the device. */
  .home-inventory-summary .summary-card,
  .home-inventory-summary .summary-card:nth-child(n + 4) {
    min-height: 0;
    padding: 0 6px;
  }

  .home-inventory-summary .summary-card:nth-child(-n + 3) {
    padding-bottom: 10px;
  }

  .home-inventory-summary .summary-card:nth-child(n + 4) {
    padding-top: 10px;
  }

  /* A 24px count in a 35px line left about 6px of empty line above and
     below it, which opened the label-to-count gap; 30px keeps it tight. */
  .home-inventory-summary .summary-card strong {
    line-height: 30px;
  }

  /* Home's action pair stays clear of the fixed QR control without changing
     the shared CTA size. */
  .home-action-grid {
    gap: 8px;
  }

  /* No decorative veil belongs behind the bottom navigation. */
  .sidebar::before {
    display: none;
  }

  /* Registering maintenance is a focused, settings-style editor opened from
     the local floating action, rather than an inline form in the list. */
  .maintenance-register-fab {
    z-index: 8;
  }

  .maintenance-register-overlay {
    position: fixed;
    z-index: 500;
    inset: 0;
    display: grid;
    align-content: start;
    gap: var(--page-content-gap);
    overflow-y: auto;
    background: var(--bg);
    /* One page gutter only: the form panel spans this content width. */
    padding: max(24px, env(safe-area-inset-top)) var(--page-gutter) calc(var(--bottom-tabbar-height) + 24px + env(safe-area-inset-bottom));
  }

  /* The overlay itself already reserves the safe area and one page gutter
     uniformly for all of its content (see .maintenance-register-overlay
     above), so the shared header must not add its own on top of that. */
  .maintenance-register-overlay .management-screen-header {
    padding: 0;
  }

  .maintenance-register-panel .item-form > label:not(.full-span) > select,
  .maintenance-register-panel .item-form > label:not(.full-span) > input,
  .maintenance-register-panel .item-form > label.full-span textarea {
    border: 1px solid var(--line) !important;
    border-radius: 10px;
    background: var(--paper) !important;
    padding-inline: 12px;
  }

  /* Compact operational rows leave room for three visible appointments in
     each independent Home list.  Their content stays on one readable line. */
  .home-schedule-panel .compact-schedule-row {
    display: flex;
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    min-width: 0;
    flex-direction: row;
    min-height: 36px;
    align-items: center;
    gap: 6px;
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 4px 10px;
    white-space: nowrap;
  }

  .home-schedule-panel .compact-schedule-row > time,
  .home-schedule-panel .compact-schedule-row > strong,
  .home-schedule-panel .compact-schedule-row > span {
    min-width: 0;
    overflow: hidden;
    color: var(--ink);
    font-size: 12px;
    font-weight: 500;
    line-height: 16px;
    text-overflow: ellipsis;
  }

  .home-schedule-panel .compact-schedule-row > time {
    flex: 0 0 auto;
  }

  .home-schedule-panel .week-row.compact-schedule-row > strong {
    flex: 0 0 auto;
  }

  .home-schedule-panel .compact-schedule-row .schedule-purpose {
    flex: 1 1 auto;
    color: var(--muted);
  }

  /* Every real render of .schedule-warning-badge today happens inside a
     compact schedule row, so this higher-specificity override -- not the
     base rule above -- is what determines the badge's actual on-screen
     padding and font-size (P056). .schedule-purpose next to it is flex: 1 1
     auto with its own ellipsis truncation, so the slightly larger pill only
     shortens that text a little rather than overflowing the row. */
  .home-schedule-panel .compact-schedule-row .schedule-warning-badge {
    flex: 0 0 auto;
    font-size: 12px;
    line-height: 16px;
    padding: 4px 10px;
  }

  .item-editor-screen,
  .item-editor-header {
    background: var(--bg) !important;
  }

  /* The item editor keeps Apple-style divider insets and compact row rhythm.
     Values are directly editable; the separators never run edge-to-edge. */
  .item-editor-panel .item-form > label:not(.full-span),
  .item-editor-panel .item-form > .tag-control,
  .item-editor-panel .item-form .item-identity-row,
  .item-editor-panel .item-form > label.full-span {
    position: relative;
    min-height: 56px;
    border-bottom: 0;
    padding-top: 6px;
    padding-bottom: 6px;
  }

  .item-editor-panel .item-form .item-identity-row {
    padding-top: var(--settings-list-inset);
  }

  .item-editor-scroll {
    padding-top: var(--settings-section-gap);
  }

  /* Dividers sit between rows only. The last row's line used to win over
     the weaker :last-child exception and showed along the card's bottom
     edge (owner, 2026-10-15). */
  .item-editor-panel .item-form > label:not(.full-span):not(:last-child)::after,
  .item-editor-panel .item-form > .tag-control:not(:last-child)::after,
  .item-editor-panel .item-form .item-identity-row:not(:last-child)::after,
  .item-editor-panel .item-form > label.full-span:not(:last-child)::after {
    position: absolute;
    right: var(--settings-list-inset);
    bottom: 0;
    left: var(--settings-list-inset);
    height: var(--settings-divider-width);
    background: var(--settings-divider-color);
    content: "";
  }

  /* Both schedule sections reserve exactly three compact rows.  Empty state
     copy therefore never changes the height of Home's fixed dashboard. */
  .home-schedule-panel .schedule-empty-state {
    display: grid;
    min-height: 126px;
    place-items: center;
    margin: 0;
    padding: 0 12px;
    color: var(--muted);
    font-size: 14px;
    font-weight: 500;
    text-align: center;
  }

  /* Customer fields share the same two-column width. Date controls are
     constrained to their cell so neither date nor gender can overflow. */
  .reservation-form-panel .customer-profile-grid {
    grid-template-columns: minmax(0, 0.7fr) minmax(0, 1.3fr);
  }

  .reservation-form-panel .customer-profile-grid input[type="date"] {
    box-sizing: border-box;
    inline-size: 100%;
    min-inline-size: 0;
    max-inline-size: 100%;
  }

  .reservation-form-panel .customer-profile-grid [data-reservation-field="phone"],
  .reservation-form-panel .customer-profile-grid [data-reservation-field="email"] {
    grid-column: 1 / -1;
  }

  /* The 3-step progress row used fixed "auto" columns sized to each label's
     unbroken text width; on narrow phones the combined width exceeded the
     screen and pushed the whole form panel into horizontal overflow. Letting
     the labels wrap (and the columns shrink to match) keeps the row inside
     the viewport. */
  .reservation-stepper {
    grid-template-columns: minmax(0, auto) minmax(10px, 1fr) minmax(0, auto) minmax(10px, 1fr) minmax(0, auto);
    column-gap: 4px;
  }

  .reservation-stepper strong {
    gap: 4px;
    font-size: 12px;
    white-space: nowrap;
  }

  /* A saved operation is always visually decisive.  Progress controls such
     as "次へ" retain their separate, right-aligned treatment. */
  .item-editor-panel .item-form .form-action,
  .maintenance-register-panel .item-form .form-action {
    width: 100%;
    margin-right: 0;
    margin-left: 0;
  }

  .form > .primary[type="submit"]:not(.form-actions-row .primary) {
    width: 100%;
  }

  .operation-registration-screen {
    position: fixed;
    z-index: 500;
    inset: 0;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    overflow: hidden;
    background: var(--bg);
    padding-top: 0;
  }

  .operation-registration-screen .reservation-registration-scroll {
    overflow-y: auto;
    padding: var(--page-content-gap) var(--mobile-page-gutter) calc(var(--bottom-tabbar-height) + 24px + env(safe-area-inset-bottom));
  }

  .operation-read-button,
  .ledger-settings-form .settings-editable-row > input[type="file"]::file-selector-button {
    min-height: 44px;
    border: 0;
    border-radius: 12px;
    background: color-mix(in srgb, var(--accent) 16%, var(--paper));
    color: var(--accent);
    font-weight: 700;
    padding: 0 14px;
  }

  /* Their press feedback is the shared call-to-action rule in kasane.css. */


  .ledger-operation-fab {
    z-index: 200;
  }

  .qr-operation-mode {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
    margin: 0 0 16px;
    border: 0;
    padding: 0;
  }

  .qr-operation-mode legend {
    grid-column: 1 / -1;
    margin-bottom: 8px;
    color: var(--ink);
    font-size: 14px;
    font-weight: 600;
  }

  .qr-operation-mode button {
    min-height: 42px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--paper);
    color: var(--ink);
    font-weight: 600;
  }

  .qr-operation-mode button.is-selected {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, var(--paper));
    color: var(--accent);
  }

  /* Home cards need a paint area around every side.  Keeping the dashboard
     fixed on mobile must not clip the lateral portion of its shared shadow. */
  .shell:has(.home-dashboard),
  .main:has(.home-dashboard),
  .main:has(.home-dashboard) .page-transition {
    overflow: visible;
  }

  html:has(.home-dashboard),
  body:has(.home-dashboard) {
    overflow: hidden;
  }

  /* Home must not let the schedule card consume the remaining viewport.
     It holds two section labels and exactly three compact rows per section. */
  .home-dashboard {
    grid-template-rows: auto 373px auto auto;
    align-content: start;
    gap: 20px;
    padding-bottom: 0;
  }

  .home-schedule-panel .home-schedule-scroll {
    padding-bottom: 0;
  }

  .home-schedule-panel .timeline-list,
  .home-schedule-panel .week-list {
    box-sizing: border-box;
    min-height: 100%;
    padding: 0 var(--settings-list-inset) var(--settings-list-inset);
  }

  .reservation-calendar {
    display: grid;
    gap: var(--settings-group-title-gap);
    padding: var(--settings-list-inset);
  }

  .calendar-toolbar {
    display: grid;
    grid-template-columns: auto 32px minmax(0, 1fr) 32px;
    align-items: center;
    gap: 6px;
  }

  .calendar-toolbar > strong {
    color: var(--accent);
    font-size: 15px;
    text-align: center;
  }

  .calendar-week-button {
    min-height: 36px;
    border: 0;
    border-radius: 9px;
    background: var(--accent);
    color: var(--paper);
    font-size: 12px;
    font-weight: 700;
    padding: 0 10px;
  }

  .calendar-week-button:active,
  .calendar-month-button:active,
  .calendar-day:active {
    transform: scale(.96);
  }

  .calendar-month-button {
    display: grid;
    width: 32px;
    height: 32px;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--accent);
  }

  .calendar-weekdays,
  .calendar-week-row {
    display: grid;
    grid-template-columns: 30px repeat(7, minmax(0, 1fr));
  }

  .calendar-weekdays {
    color: var(--muted);
    font-size: 11px;
    text-align: center;
  }

  .calendar-grid {
    display: grid;
    gap: 4px;
  }

  .calendar-week-row {
    gap: 4px;
  }

  .calendar-row-week-button {
    min-height: 40px;
    border: 0;
    border-radius: 7px;
    background: var(--accent);
    color: var(--paper);
    font-size: 10px;
    font-weight: 700;
  }

  .calendar-row-week-button:disabled {
    opacity: .28;
  }

  .calendar-day {
    position: relative;
    display: grid;
    min-width: 0;
    min-height: 40px;
    place-items: center;
    border: 0;
    border-radius: 9px;
    background: transparent;
    color: var(--ink);
    font-size: 13px;
  }

  .calendar-day.is-today > span {
    color: var(--accent);
    font-weight: 800;
  }

  .calendar-day.is-selected {
    background: color-mix(in srgb, var(--accent) 14%, var(--paper));
    color: var(--accent);
    font-weight: 700;
  }

  .calendar-day.is-holiday,
  .calendar-weekdays .is-sunday {
    color: var(--danger);
  }

  .calendar-day.is-saturday,
  .calendar-weekdays .is-saturday {
    color: #2C4394;
  }

  .calendar-day.is-closed-red { color: var(--danger); }
  .calendar-day.is-closed-blue { color: #2C4394; }
  .calendar-day.is-closed-yellow { color: #b8860b; }
  .calendar-day.is-closed-purple { color: var(--accent); }
  .calendar-day.is-closed-pink { color: #d75a9a; }
  .calendar-day.is-closed-orange { color: #d97706; }
  .calendar-day.is-closed-none { color: inherit; }

  .reservation-calendar .empty-state,
  .reservation-calendar [class*="dashed"] {
    border: 0 !important;
    border-image: none;
  }

  /* One badge per kind, sitting side by side in the cell's corner. A single
     total could not say which kind a day held, and the two kinds already read
     as a pair everywhere else in the ledger. */
  .calendar-day-counts {
    position: absolute;
    right: 3px;
    bottom: 2px;
    display: flex;
    gap: 2px;
  }

  .calendar-day b {
    display: grid;
    min-width: 15px;
    height: 15px;
    place-items: center;
    border-radius: 50%;
    font-size: 9px;
    line-height: 1;
  }

  /* The ledger's own 試着/本番 badge colours, borrowed exactly. */
  .calendar-day b.calendar-day-count--fitting,
  .calendar-legend-swatch--fitting {
    background: rgba(101, 24, 104, 0.12);
    color: var(--accent);
  }

  .calendar-day b.calendar-day-count--event,
  .calendar-legend-swatch--event {
    background: var(--accent);
    color: var(--paper);
  }

  /* What the two count-badge colours mean, above the weekday row. The dots are
     the badges' own fills, so the key can never drift from the cells. */
  .calendar-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    margin: 0 0 6px;
    color: var(--muted);
    font-size: 12px;
    line-height: 1.4;
  }

  .calendar-legend > span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
  }

  .calendar-legend-swatch {
    width: 10px;
    height: 10px;
    border-radius: 50%;
  }

  /* The selected-day list is a header plus the same divider-separated rows as
     the ledger's own 予約一覧, so it spans its panel edge to edge instead of
     sitting in a second rounded card inside one. */
  .calendar-selection-list {
    display: grid;
    gap: 0;
    margin-inline: calc(-1 * var(--settings-list-inset));
    padding: 0;
    border-radius: 0;
    background: var(--paper);
    box-shadow: none;
    overflow: hidden;
  }

  .calendar-selection-list > strong {
    min-height: 42px;
    margin: 0;
    border-radius: 0;
    background: var(--accent);
    color: var(--paper);
    font-size: 14px;
    padding: 12px var(--settings-list-inset);
  }

  .calendar-selection-list .calendar-row {
    min-height: 52px;
    padding-right: var(--settings-list-inset);
    padding-left: var(--settings-list-inset);
  }

  /* Nothing selected-day: the sentence sits in the middle of its white area,
     not under the band (owner, 2026-10-08). */
  .calendar-selection-list > .empty-state {
    display: grid;
    min-height: 96px;
    margin: 0;
    padding: 0 var(--settings-list-inset);
    place-items: center;
  }

  /* The purple ledger header remains at the top only; a long body must
     finish on the shared app background rather than exposing the shell. */
  .main:has(.ledger-phase-stack),
  .main:has(.ledger-phase-stack) .page-transition,
  .ledger-phase-stack .tab-content {
    background: var(--bg) !important;
  }

  .ledger-page-title {
    border-top: 0 !important;
    outline: 0;
  }

  .calendar-display-settings .store-setting-row > span:first-child {
    white-space: nowrap;
  }

  /* The ledger header is a fixed accent surface. Only the tab body scrolls,
     so overscroll cannot reveal a stale route colour beneath its content.
     Document pinning is shared; this rule only pins the ledger shell. */
  .shell:has(.ledger-phase-stack) {
    height: 100dvh;
    overflow: hidden;
    overscroll-behavior: none;
    background: var(--bg) !important;
  }

  .main:has(.ledger-phase-stack),
  .main:has(.ledger-phase-stack) .page-transition {
    display: flex;
    height: 100%;
    min-height: 0;
    overflow: hidden;
    padding: 0 !important;
    background: var(--bg) !important;
  }

  .main:has(.ledger-phase-stack) .page-transition {
    flex-direction: column;
  }

  .main:has(.ledger-phase-stack) .page-transition > .ledger-page-title {
    flex: 0 0 auto;
    margin: 0 !important;
    border: 0 !important;
    background: var(--accent) !important;
    height: calc(64px + var(--settings-group-title-gap)) !important;
    min-height: calc(64px + var(--settings-group-title-gap)) !important;
    padding-bottom: var(--settings-group-title-gap) !important;
  }

  .main:has(.ledger-phase-stack) .page-transition > .ledger-page-title {
    min-height: 58px;
  }

  .ledger-phase-stack {
    flex: 1 1 auto;
    min-height: 0;
    height: auto !important;
    overflow: hidden;
    padding: 0 !important;
    background: var(--bg) !important;
  }

  /* Full-screen ledger registrations keep their safe area and title bar on
     the same accent surface, while their form remains on the app background. */
  .operation-registration-screen,
  .sales-registration-screen {
    background: var(--accent);
  }

  .operation-registration-screen .reservation-registration-scroll,
  .sales-registration-screen .reservation-registration-scroll {
    background: var(--bg);
  }

  /* The reservation list should end as tightly as the checkout and return
     lists; section spacing belongs outside its card. */

  .ledger-phase-stack .reservation-list-panel .row-link-table a {
    min-height: 0;
  }

  /* Keep maintenance creation at the same predictable lower-right anchor as
     the inventory and ledger actions, even when its list is scrolled. */
  .maintenance-register-fab {
    z-index: 200 !important;
  }

  /* Settings lists use one divider contract: rules are always drawn as an
     inset pseudo-element, never as an edge-to-edge border.  This also covers
     the custom blocks used by store hours and regular-closure settings. */
  .store-settings-form .store-settings-list > .full-span {
    position: relative;
    border-bottom: 0;
    padding: 8px var(--settings-list-inset);
  }

  /* Customer editing is an internal staff editor, not a customer-facing
     intake form.  Reuse the same quiet list surface as item editing so its
     labels and controls cannot drift into separate floating boxes. */
  .customer-management-form {
    width: 100%;
    padding: 0;
    gap: var(--settings-section-gap);
  }

  .customer-management-form .form-group-section {
    gap: var(--settings-group-title-gap);
    padding: 0;
    border: 0;
  }

  .customer-management-form .form-group-section > h2 {
    margin: 0;
    padding: 0;
  }

  .customer-management-form .form-group-grid {
    grid-template-columns: 1fr;
    gap: 0;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--paper);
    box-shadow: none;
  }

  .customer-management-form .form-group-grid > label,
  .customer-management-form .form-group-grid > .name-row > label,
  .customer-management-form .form-group-grid > .customer-profile-grid > label {
    display: grid;
    grid-template-columns: var(--settings-label-value-columns);
    align-items: center;
    gap: 12px;
    min-height: var(--settings-row-height);
    margin: 0;
    padding: 8px var(--settings-list-inset);
    border-bottom: var(--settings-divider-width) solid var(--settings-divider-color);
    color: var(--settings-label-color);
    font-size: var(--ui-row-label-size);
    font-weight: 400;
  }

  .customer-management-form .form-group-grid > .name-row {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: 1fr;
    gap: 0;
  }

  .customer-management-form .form-group-grid > .name-row > label:last-child,
  .customer-management-form .form-group-grid > label:last-child {
    border-bottom: 0;
  }

  .customer-management-form .form-group-grid > label > input:where(:not(.value-pill, .value-pill-control)),
  .customer-management-form .form-group-grid > label > select:where(:not(.value-pill, .value-pill-control)),
  .customer-management-form .form-group-grid > .name-row > label > input:where(:not(.value-pill, .value-pill-control)),
  .customer-management-form .form-group-grid > .customer-profile-grid > label > input:where(:not(.value-pill, .value-pill-control)),
  .customer-management-form .form-group-grid > .customer-profile-grid > label > select:where(:not(.value-pill, .value-pill-control)) {
    width: 100%;
    min-height: 40px;
    margin: 0;
    border: 0 !important;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: var(--settings-value-color);
    text-align: right;
  }

  .customer-management-form .form-group-grid > label > .postal-inline {
    display: grid;
    grid-column: 2;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px;
    min-width: 0;
  }

  .customer-management-form .form-group-grid > label > .postal-inline > input {
    min-width: 0;
    min-height: 40px;
    border: 0 !important;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    text-align: right;
  }

  /* Keep the historic wrapper as a real one-column list.  Mobile Safari does
     not consistently retain grid placement for form controls under
     `display: contents`, which is why the previous conversion still rendered
     this pair as a two-column field in the installed app. */
  .customer-management-form .form-group-grid > .customer-profile-grid {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    min-width: 0;
  }

  .customer-management-form .form-group-grid > .customer-profile-grid .age-preview {
    grid-column: 2;
    justify-self: end;
    color: var(--settings-value-color);
    font-weight: 400;
  }

  /* Native controls align their selected value with the right edge of the
     settings value column. */
  .store-settings-form .store-editable-control input:where(:not(.value-pill, .value-pill-control)),
  .store-settings-form .store-editable-control select:where(:not(.value-pill, .value-pill-control)) {
    color: var(--settings-value-color);
    font-size: var(--settings-value-size);
    font-weight: var(--ui-supporting-text-weight);
    text-align: right;
    text-align-last: right;
  }

  .store-settings-form .store-settings-section-title.is-reserved {
    visibility: hidden;
  }

  .store-settings-form .store-settings-save {
    width: 100%;
    margin: 24px 0 40px;
  }

  .customer-create-fab {
    z-index: 8 !important;
  }
}

/* Detail lists use the same single-column inset-divider pattern as settings. */
.item-detail-panel {
  overflow: hidden;
}

.item-detail-panel .item-detail-hero {
  display: grid;
  grid-template-columns: 1fr;
  justify-items: center;
  gap: 12px;
  border-bottom: 0;
  background: var(--paper);
  padding: var(--settings-list-inset);
}

.settings-detail-list {
  display: block;
  border-top: var(--settings-divider-width) solid var(--settings-divider-color);
  background: var(--paper);
  padding: 0;
}

.settings-detail-row {
  position: relative;
  display: grid;
  grid-template-columns: var(--settings-label-value-columns);
  align-items: center;
  min-height: var(--settings-row-height);
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: var(--settings-row-padding-block) var(--settings-list-inset);
}

.settings-detail-row:not(:last-child)::after,
.settings-inset-divider:not(:last-child)::after {
  position: absolute;
  right: var(--settings-list-inset);
  bottom: 0;
  left: var(--settings-list-inset);
  height: var(--settings-divider-width);
  background: var(--settings-divider-color);
  content: "";
}

.settings-inset-divider {
  position: relative;
  border-bottom: 0;
}

.settings-detail-row > span {
  /* Grid items default to a min-width of their own content, so a label
     longer than the shared minmax() floor below used to push the column
     wider than the row and get silently clipped by this list's
     overflow: hidden instead of wrapping (P038). min-width: 0 lets this column actually
     shrink to that floor, and overflow-wrap makes it wrap there instead
     of overflowing, matching the value column's own overflow-safety. */
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--settings-label-color);
  font-size: var(--settings-label-size);
  font-weight: var(--ui-row-label-weight);
}

.settings-detail-row > strong {
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
  color: var(--settings-value-color);
  font-size: var(--settings-value-size);
  font-weight: var(--ui-row-label-weight);
  text-align: right;
}

.item-qr-section {
  display: grid;
  gap: var(--settings-group-title-gap);
  margin-top: var(--settings-section-gap);
}

.item-qr-section > h2 {
  margin: 0;
  padding-inline: 0;
  color: var(--settings-group-title-color);
  font-size: var(--ui-section-title-size);
  font-weight: var(--ui-section-title-weight);
}

.item-qr-panel {
  margin-top: 0;
  overflow: hidden;
}

.item-qr-panel .item-qr-body {
  width: 100%;
  padding: var(--settings-list-inset);
}

.item-qr-panel .item-qr-action {
  width: 100%;
}

/* This stylesheet is loaded last. Keep the employee editor as an opaque page
   and preserve its action footer instead of reviving legacy two-row rules. */
.employee-editor-screen {
  position: fixed !important;
  z-index: 30000 !important;
  /* Below the developer banner when one is shown (the variable is set only then). */
  inset: var(--developer-banner-height, 0px) 0 0 !important;
  display: grid !important;
  grid-template-rows: auto minmax(0, 1fr) !important;
  overflow: hidden !important;
  background: var(--bg) !important;
}

.employee-editor-header {
  display: grid !important;
  grid-template-columns: 44px minmax(0, 1fr) 44px !important;
  align-items: center;
  min-height: 68px;
  padding: max(12px, env(safe-area-inset-top)) var(--page-gutter) 12px !important;
  background: var(--bg) !important;
  box-shadow: none;
}

.employee-editor-header h1 {
  margin: 0;
  color: var(--accent) !important;
  font-size: var(--ui-page-title-size) !important;
  font-weight: var(--ui-page-title-weight) !important;
  text-align: center;
}

.employee-editor-back {
  display: grid !important;
  width: 44px !important;
  height: 44px !important;
  padding: 0 !important;
  place-items: center;
  border: 0 !important;
  border-radius: 50% !important;
  background: var(--paper) !important;
  box-shadow: none;
  color: var(--accent) !important;
  font-size: 22px !important;
  line-height: 1 !important;
}

.employee-editor-scroll {
  min-height: 0 !important;
  overflow-y: auto !important;
  padding: var(--page-content-gap) var(--page-gutter) calc(24px + env(safe-area-inset-bottom)) !important;
}

.employee-editor-row {
  position: relative;
  display: grid !important;
  grid-template-columns: var(--settings-label-value-columns) !important;
  align-items: center;
  gap: 12px;
  min-height: var(--settings-row-height) !important;
  margin: 0 !important;
  padding: 8px var(--settings-list-inset) !important;
  border: 0 !important;
}

.employee-editor-row > span {
  min-width: 0;
  color: var(--settings-label-color);
  font-size: var(--ui-row-label-size);
  font-weight: 400;
}

.employee-editor-row em {
  color: var(--danger);
  font-style: normal;
}

.employee-editor-row input:where(:not(.value-pill, .value-pill-control)),
.employee-editor-row select:where(:not(.value-pill, .value-pill-control)) {
  width: 100% !important;
  min-width: 0 !important;
  min-height: 40px !important;
  height: auto !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none;
  color: var(--settings-value-color) !important;
  font: inherit;
  text-align: right;
}

.employee-editor-row:not(:last-child)::after {
  position: absolute;
  right: var(--settings-list-inset);
  bottom: 0;
  left: var(--settings-list-inset);
  height: var(--settings-divider-width);
  background: var(--settings-divider-color);
  content: "";
}

  .employee-editor-actions {
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) !important;
  gap: 10px;
  margin-top: var(--settings-section-gap);
  padding: 0;
  background: transparent !important;
  box-shadow: none;
}

.employee-editor-actions:has(.employee-editor-save:only-child) {
  grid-template-columns: minmax(0, 1fr) !important;
}

.item-detail-panel .detail-thumb { width: min(100%, 280px); height: 280px; border-radius: 20px; }
.item-detail-panel .item-detail-hero > div:last-child { width: 100%; text-align: center; }

  .employee-editor-save {
  min-height: 52px !important;
  margin: 0 !important;
  border-radius: var(--radius-sm) !important;
  font: inherit !important;
  font-weight: 600 !important;
}

.employee-editor-save {
  width: 100% !important;
  border: 0 !important;
  background: var(--accent) !important;
  color: #fff !important;
}

  .employee-editor-text-action {
    width: fit-content !important;
    min-height: auto !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    color: var(--ink) !important;
    font: inherit !important;
    font-size: var(--ui-row-label-size) !important;
    font-weight: 400 !important;
    text-align: center;
  }

  .employee-editor-text-action:disabled { opacity: 0.55; }

.employee-editor-actions {
  justify-items: center;
}

.employee-editor-save {
  justify-self: stretch;
}

/* 台帳の登録 (貸出・返却・販売): cards of settings rows, one section gap
   apart; checks and the QR field are values of their rows. */
.ledger-settings-form {
  display: grid;
  gap: var(--settings-section-gap);
}

.settings-editable-list > .settings-editable-row.settings-check-row > input {
  justify-self: end;
  width: 22px;
}

.operation-qr-control {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.operation-qr-control > input {
  flex: 1;
  min-width: 0;
  min-height: 40px;
  border: 0;
  background: transparent;
  color: var(--settings-value-color);
  font: inherit;
  text-align: right;
}

/* A photo picker in a ledger row (返却時の状態): the row is stacked, so the
   native control has the card's width, and its button takes the look of the
   QR 読み取り button (.operation-read-button) through that rule's selector list. */
.ledger-settings-form .settings-editable-row > input[type="file"] {
  justify-self: start;
  text-align: left;
  text-align-last: left;
  font-size: 15px;
}

.ledger-settings-form .settings-editable-row > input[type="file"]::file-selector-button {
  margin-right: 12px;
  font: inherit;
  font-weight: 700;
}

.ledger-notes-card textarea {
  width: 100%;
  min-height: 88px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  resize: vertical;
}

/* One action on its own as a row of a white card (SettingsActionRow): the
   words in the accent colour, red when it cannot be undone, the row's full
   width as the target. Height, type size and inset match the settings rows
   beside it; rows in one card are divided like any list. */
.settings-action-row {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  min-height: var(--settings-row-height);
  padding: 0 var(--settings-list-inset);
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 17px;
  font-weight: 400;
  line-height: 22px;
  text-align: left;
  cursor: pointer;
}

.settings-action-row--danger {
  color: var(--danger);
}

/* 外す at the trailing edge of a chosen entry (SettingsRemovableRow). A long
   item name wraps onto a second line with the same space above and below it
   as a multi-line detail row; one line keeps the ordinary row height, and
   外す keeps a 44px target by reaching into that padding. */
.store-settings-form .store-settings-list .store-editable-row.settings-removable-row {
  height: auto;
  min-height: var(--settings-row-height);
  padding-block: var(--settings-row-wrap-padding);
}

.settings-row-remove {
  min-height: 44px;
  margin-block: -6px;
  border: 0;
  background: transparent;
  color: var(--danger);
  font: inherit;
  cursor: pointer;
}

/* The confirm step's 修正 card sits one section below the summary card. */
.reservation-confirm-edit-card {
  margin-top: var(--settings-section-gap);
}

.settings-action-row--flush {
  padding-inline: 0;
}

.settings-action-row:disabled {
  color: var(--muted);
  cursor: default;
}

.settings-action-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.settings-action-row:not(:last-child)::after {
  position: absolute;
  right: var(--settings-list-inset);
  bottom: 0;
  left: var(--settings-list-inset);
  height: var(--settings-divider-width);
  background: var(--list-separator);
  content: "";
}

/* Reusable contract for a single unboxed text action.  Full-width filled
   submit buttons intentionally do not opt into this pattern. */
.text-link-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  justify-self: center;
  width: fit-content;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: var(--settings-label-size);
  font-weight: 400;
  text-align: center;
}

.text-link-cta--brand {
  color: var(--accent) !important;
}

.text-link-cta--neutral {
  color: var(--ink) !important;
}

.text-link-cta--danger {
  color: var(--danger) !important;
}

.issued-credential-detail {
  display: grid;
  gap: 12px;
  min-width: 0;
}

.issued-credential-detail > p {
  margin: 0;
}

.issued-credential-value {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
}

.issued-credential-value output {
  overflow-wrap: anywhere;
  color: var(--settings-label-color);
  font-weight: 600;
  letter-spacing: 0.08em;
}



/* A long or multi-line value (備考, 利用商品) reads the way iPhone Settings
   shows long text: label and disclosure on the first line, the text below at
   the row's full width, left-aligned. A short value keeps the ordinary
   centred row; SettingsDetailRow decides which. The list prefix outranks both
   the editable row's three-column grid and the shared right-aligned value. */
.settings-detail-list > .settings-detail-row.is-multiline {
  grid-template-columns: minmax(0, 1fr) auto;
  row-gap: 4px;
  align-items: center;
  padding-block: var(--settings-row-wrap-padding);
}

.settings-detail-list > .settings-detail-row.is-multiline > strong {
  grid-column: 1 / -1;
  grid-row: 2;
  text-align: left;
  white-space: pre-wrap;
}

.settings-detail-list > .settings-detail-row.is-multiline > i {
  grid-column: 2;
  grid-row: 1;
}

/* Shared app surface. Keep it a single colour so the standalone iOS status
   area and the content surface read as one continuous background. */
.brand-background {
  position: fixed;
  z-index: 0;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  background: var(--bg);
}

.brand-background__shape {
  display: none;
}

.brand-background__shape--primary {
  top: -34vw;
  right: -22vw;
  background: #d99bdf;
}

.brand-background__shape--secondary {
  top: -20vw;
  left: -42vw;
  background: #9d54a3;
  opacity: 0.42;
}

.login-page {
  position: relative;
  isolation: isolate;
}

.login-page > :not(.brand-background) {
  position: relative;
  z-index: 1;
}

/* Top-level screens opt in through AppShell rather than relying on a
   descendant selector.  This keeps the entire central page surface transparent
   on mobile Safari as well as desktop browsers. */
.shell--brand-backdrop,
.shell--brand-backdrop .main,
.shell--brand-backdrop .page-transition {
  background: transparent;
}

.shell--brand-backdrop .main {
  position: relative;
  z-index: 1;
}

/* The inventory CSV importer is rendered through a body portal. It must own
   the complete standalone viewport, including the iOS safe area, and its
   native file control must never expand the white import surface. */
.csv-import-screen {
  box-sizing: border-box;
  padding-top: env(safe-area-inset-top);
  background: var(--bg);
}

/* .csv-import-screen already reserves the safe area for all of its content
   (see the padding-top rule above), so the shared header must not add its
   own on top of that -- unlike a routed ManagementScreen destination, which
   owns the full edge-to-edge surface by itself. */
.csv-import-screen .management-screen-header {
  padding-top: 0;
}

.csv-import-screen .csv-import-scroll {
  padding-right: var(--page-gutter);
  padding-left: var(--page-gutter);
}

.csv-import-screen .csv-import-content,
.csv-import-screen .csv-grid,
.csv-import-screen .csv-feature-group,
.csv-import-screen .csv-box {
  width: 100%;
  max-inline-size: 100%;
  min-inline-size: 0;
}

.csv-import-screen .csv-box > input[type="file"],
.csv-import-screen .csv-box > button {
  inline-size: 100%;
  max-inline-size: 100%;
  min-inline-size: 0;
}

.csv-missing-header-confirmation {
  display: grid;
  gap: 12px;
}

.csv-missing-header-confirmation p {
  margin: 0;
  color: var(--muted);
}

.csv-missing-header-confirmation > div {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.csv-missing-header-confirmation button {
  min-inline-size: 0;
}

/* Only the management lists remain white surfaces. The surrounding page and
   title area stay transparent, so there is no rectangular white page behind
   the cards. */
.shell--brand-backdrop .settings-page .settings-menu .settings-list {
  background: rgb(255 255 255 / 94%);
  box-shadow: none;
}

/* A standalone destructive action must not reveal the pale page through its
   only card.  Unlike grouped settings rows, its whole surface is visible. */
.management-subpage .settings-list.settings-logout-list {
  background: var(--paper) !important;
}

/* The account heading is intentionally absent. Keep the normal section gap
   so the destructive, standalone action cannot read as another preference. */
.settings-logout-group .settings-logout-list { margin-top: 0; }

/* The bottom tab bar belongs to the viewport, never to a scrolling setting
   list or the visual viewport that contracts for the software keyboard. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .sidebar {
    position: fixed !important;
    right: 0;
    bottom: 0;
    left: 0;
    transform: none !important;
  }

  .page-transition {
    isolation: isolate;
  }
}

/* One trailing-control contract for selects, values, and switches.  The
   control column owns the trailing edge; individual settings screens never
   position a switch or selected value themselves. */
.store-settings-form .store-editable-control,
.settings-toggle-row > .store-editable-control {
  display: flex;
  grid-column: 2;
  justify-content: flex-end;
  min-width: 0;
}

.settings-toggle-row-label,
.store-settings-form .store-editable-row > span:first-child {
  min-width: 0;
  color: var(--settings-label-color) !important;
  font-size: var(--settings-label-size) !important;
  font-weight: var(--ui-row-label-weight) !important;
  line-height: var(--ui-row-label-line-height);
  /* keep-all alone forbids every fallback break, so a Japanese label with no
     punctuation ran straight out of its column and under the switch:
     "本日の予約サマリーをメールで通知" was being cut at "通" (P060). anywhere
     is the escape hatch, the same pairing the navigation rows and the
     grey-heading copy already use (P048/P049). */
  overflow-wrap: anywhere;
  word-break: keep-all;
}

.settings-toggle-row-label > small {
  display: block;
  margin-top: 6px;
  color: var(--settings-value-color);
  font-size: 14px;
  font-weight: 400;
}

/* In place of a switch the person cannot use: the value colour of any other
   read-only row, on one line. */
.settings-toggle-row-locked {
  color: var(--settings-value-color);
  font-size: var(--ui-row-label-size);
  white-space: nowrap;
}

.email-notification-preferences {
  display: grid;
  gap: var(--settings-section-gap);
}

.notification-preference {
  display: grid;
  gap: var(--settings-heading-gap);
}

.notification-preference .store-settings-section {
  border-radius: var(--settings-list-radius);
  background: var(--settings-list-surface);
}

.notification-preference-detail {
  margin: 0;
  padding-inline: var(--settings-list-inset);
  color: var(--list-secondary-label);
  font-size: 13px;
  font-weight: 400;
  line-height: 17px;
}

/* Shared conditional-detail wrapper is used for enabled notification guidance
   and return-condition notes. */
.conditional-detail {
  min-width: 0;
}

.conditional-detail > p {
  margin: 0;
}

/* Form surfaces use the same gutter and value-control sizing.  These rules
   deliberately override earlier page-specific right-alignment patches. */
.maintenance-register-panel .item-form > label,
.item-editor-panel .item-form > label {
  min-width: 0;
  padding-inline: var(--settings-list-inset);
}

.reservation-table tr.is-overdue td {
  background: var(--warning-bg);
}

/* Same pill geometry as .badge (radius/padding/font-size) -- only colour and
   usage differ between status pills, not shape (P056). */
.overdue-badge {
  display: inline-block;
  border-radius: 999px;
  background: #CD4643;
  color: #fff;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}

/* Ledger lists are compact records, not desktop tables.  This shared card
   surface keeps every field readable without horizontal scrolling. */
.ledger-record-list {
  display: grid;
  gap: 8px;
  padding: var(--settings-list-inset);
}

.ledger-record-card {
  position: relative;
  display: grid;
  gap: 8px;
  min-inline-size: 0;
  color: var(--ink);
  /* The shared compact card owns the surface. The extra right inset is only
     for the chevron accessory, not a third card-padding size. */
  padding: var(--card-padding-small) calc(var(--card-padding-small) + 18px) var(--card-padding-small) var(--card-padding-small);
  text-decoration: none;
}

.ledger-record-card.is-overdue {
  background: var(--warning-bg);
}

.ledger-record-lead {
  display: flex;
  min-inline-size: 0;
  align-items: center;
  gap: 8px;
}

.ledger-record-lead strong {
  min-inline-size: 0;
  color: var(--ink);
  font-size: 16px;
  line-height: 1.35;
  overflow-wrap: break-word;
  word-break: normal;
  line-break: strict;
  text-wrap: pretty;
}

.ledger-record-lead span {
  color: var(--muted);
  font-size: 14px;
}

.ledger-record-lead em {
  flex: 0 0 auto;
  border-radius: 999px;
  background: var(--chip-bg);
  color: var(--muted);
  font-size: 12px;
  font-style: normal;
  padding: 3px 8px;
}

/* .ledger-record-lead em (above) is the shared chip geometry for every badge
   in a ledger record's lead line -- 試着/本番 kind badges as well as this one
   -- and every real .overdue-badge render lives inside it, so its own
   padding: 3px 8px silently outranked the bare .overdue-badge rule this
   selector shares a name with. This override's two classes (0,2,0) already
   beat that shared rule's one class + tag (0,1,1), so padding alone is
   enough here to reach .badge's shape without touching the kind badges'
   own geometry (P056). */
.ledger-record-lead .overdue-badge {
  background: var(--warning-bg);
  color: var(--danger);
  padding: 4px 10px;
}

/* 試着＝紫、本番＝紫の濃淡違い: the same accent purple at two depths so the
   two reservation kinds read as a pair, not unrelated colors. */
.ledger-record-lead .reservation-kind-badge--fitting {
  background: rgba(101, 24, 104, 0.12);
  color: var(--accent);
}

.ledger-record-lead .reservation-kind-badge--event {
  background: var(--accent);
  color: #fff;
}

.ledger-record-details {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
}

.ledger-record-details > span {
  display: grid;
  align-content: start;
  min-inline-size: 0;
  gap: 2px;
  color: var(--ink);
  font-size: 12px;
  line-height: 1.35;
  overflow-wrap: break-word;
  word-break: normal;
  line-break: strict;
  text-wrap: pretty;
}

.ledger-record-details b {
  display: block;
  color: var(--muted);
  font-size: 11px;
  font-weight: 500;
}

.ledger-record-chevron {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-end: 8px;
  color: var(--muted-light);
  font-size: 18px;
  transform: translateY(-50%);
}

/* Detail inventory reserves the status box without squeezing the product
   identity; the box moves below the edit control on phone widths. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .inventory-page .inventory-mode-detail {
    --inventory-detail-image-size: 112px;
  }

  .inventory-page .inventory-mode-detail .inventory-card {
    grid-template-columns: var(--inventory-detail-columns) !important;
    height: auto !important;
  }

  .inventory-page .inventory-mode-detail .inventory-card-main .inventory-card-title {
    padding-inline-end: 0 !important;
  }

  .inventory-page .inventory-card-status-box {
    position: static !important;
    grid-column: 1 / -1;
    width: auto !important;
  }
}

/* Store-shared product master maintenance.  These use the same form and
   divider tokens as other management destinations rather than page-local
   spacing rules. */
.item-master-settings {
  display: grid;
  gap: var(--settings-section-gap);
}

.item-master-panel > label {
  display: grid;
  gap: 6px;
  color: var(--ink);
  font-weight: 400;
}

.item-master-panel,
.item-master-values {
  margin: 0;
}

.item-master-form {
  display: grid;
  gap: 14px;
}

.item-master-value-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--settings-row-height);
}

.item-master-value-row + .item-master-value-row {
  border-top: 1px solid var(--settings-divider-color);
}

.item-master-value-actions {
  display: inline-flex;
  flex: 0 0 auto;
  gap: 12px;
}

.item-master-value-actions button {
  border: 0;
  background: transparent;
  color: var(--accent, #651868);
  padding: 6px 2px;
}

.item-master-value-actions .button.danger {
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--danger);
  color: #fff;
  padding: 6px 10px;
}

.item-master-multi-select select {
  min-block-size: 88px;
}

/* Final UI contract.  These are shared primitives, intentionally placed
   after legacy per-page rules so a route transition cannot revive an older
   surface, inset, or control geometry. */
body,
button,
input,
select,
textarea { font-family: var(--app-system-font); }

:is(h1, .page-title h1, .page-header h1, .management-screen-header h1, .settings-page-header h1) {
  font-family: var(--app-display-font);
}

/* The management menu reuses one icon wrapper.  Giving that wrapper the
   Settings-style treatment updates every current and future menu row. */
.settings-menu .settings-row-icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: var(--accent) !important;
  color: #fff !important;
  font-size: 16px;
  box-shadow: none;
}

.settings-menu .settings-row-danger .settings-row-icon {
  background: var(--chip-bg) !important;
  color: var(--danger) !important;
}

/* margin/padding belong to the grey-heading contract later in this file. */
:is(.store-settings-section-title > h2, .settings-detail-section-heading > h2, .management-screen-scroll .form-group-section > h2) {
  font-weight: var(--ui-section-title-weight) !important;
}


.field-error {
  display: block;
  grid-column: 1 / -1;
  min-width: 0;
  margin: 0;
  color: var(--danger);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.4;
}

.settings-toggle-row { align-items: center !important; }
.settings-toggle-row > .store-editable-control { margin-left: auto; }
.notification-preference .settings-toggle-row-label { line-height: 1.45; word-break: normal; overflow-wrap: anywhere; }
.notification-preference .settings-toggle-row-label > small { font-size: 13px; line-height: 1.45; }

.csv-feature-group > .csv-box { background: var(--settings-list-surface); }

.view-mode-switch { display: inline-flex; padding: 2px; border-radius: 999px; }
.view-mode-button { border-radius: 50% !important; overflow: hidden; }
.view-mode-button.is-active { border-radius: 999px !important; }

/* The ledger and management pages are full-screen route surfaces.  Earlier
   style batches each owned part of this layout and used competing global
   backgrounds/heights; a client route remount could therefore expose the old
   accent backdrop and clip the title.  The shell owns the background, while
   only the ledger body owns scrolling. */
.shell:has(.management-screen) { background: var(--bg) !important; }

.main:has(.ledger-phase-stack),
.main:has(.management-screen),
.main:has(.ledger-phase-stack) .page-transition,
.main:has(.management-screen) .page-transition { background: var(--bg) !important; }

.main:has(.ledger-phase-stack) .page-transition {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  height: auto;
  overflow: visible;
}

.main:has(.ledger-phase-stack) .page-transition > .ledger-page-title {
  display: block !important;
  flex: 0 0 auto;
  min-height: 58px;
  height: auto !important;
}

.ledger-phase-stack { min-height: 0; height: auto !important; }

@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .main:has(.ledger-phase-stack) .page-transition { min-height: calc(100dvh - var(--bottom-tabbar-height)); }
}

/* Maintenance list headings follow every other management surface. */
.maintenance-stack {
  gap: var(--settings-section-gap);
}

.maintenance-stack .management-settings-group > h2 {
  margin-bottom: var(--settings-heading-gap);
}

/* .store-setting-row lays out three tracks (label / value / chevron). A
   navigation row that carries no value element still paid for the middle
   track, so its label was squeezed into the 0.8fr label column -- 121px of a
   266px row. Every notification label then wrapped onto two lines, and the
   overflow-wrap: anywhere below broke them mid-word ("リマイン" / "ド").
   Rows that do have a value keep all three tracks. */
.store-settings-form .store-settings-navigation-row:not(:has(> strong)) {
  grid-template-columns: minmax(0, 1fr) 20px;
}

.store-settings-navigation-row > span:first-child {
  min-width: 0;
  font-weight: var(--ui-row-label-weight) !important;
  line-height: 1.35;
  /* keep-all prefers breaks at phrase boundaries, but on its own it forbids
     every fallback break: a label with no punctuation, such as
     "着付け担当未設定のリマインド", then ran straight out of its column and
     under the chevron. anywhere is the escape hatch, exactly as in the
     grey-heading copy rules (P048/P049). */
  overflow-wrap: anywhere;
  word-break: keep-all;
}

/* Authentication is a form on a white surface.  Its inputs intentionally use
   a soft depth cue instead of the generic gray form outline. */
.login-card {
  border: 0;
  border-radius: var(--radius);
}

.login-page .form input:not([type="hidden"]),
.login-page .form select,
.login-page .form textarea {
  border: 0;
  box-shadow: none;
}

.login-page .form input:not([type="hidden"]):focus,
.login-page .form select:focus,
.login-page .form textarea:focus {
  border-color: transparent;
  box-shadow: none;
}

/* The automatic passkey ceremony is isolated from the password form. It is
   route-level rather than document-level so ordinary pages retain --bg. */
.passkey-login-gate {
  position: fixed;
  z-index: 500;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--accent);
}

.passkey-login-gate .loading-dots span {
  background: var(--paper);
}

/* Every child of .login-page is its own z-index:1 layer, so the gate's
   z-index stays inside the login card's layer and the links after the card
   painted over it: the loading screen showed 利用規約 and 提供者ログイン
   (owner, 2026-09-29). They belong to the sign-in form, not the check. */
.login-page:has(.passkey-login-gate) > :is(.login-legal-links, .login-provider-link) {
  visibility: hidden;
}

.menu-information-section,
.sync-device-settings,
.passkey-settings {
  display: grid;
  gap: var(--settings-heading-gap);
}

/* One iOS-settings-like contract for every settings, management, and detail
   list.  These rules deliberately use the dedicated tokens instead of the
   application's general cards so that CTAs and branded surfaces stay purple. */
:is(
  .settings-menu .settings-list,
  .management-subpage .settings-list,
  .customer-directory-list,
  .customer-settings-list,
  .customer-next-section,
  .history-box,
  .employee-directory-list,
  .employee-editor-list,
  .audit-filter-surface,
  .audit-log-list,
  .security-recovery-list,
  .sync-device-panel .management-card-list,
  .csv-feature-group > .csv-box,
  .store-settings-form .store-settings-group .store-settings-section,
  .reservation-settings-list,
  .settings-detail-list,
  .maintenance-detail-panel .detail-list
) {
  border-radius: var(--settings-list-radius) !important;
  background: var(--settings-list-surface) !important;
  overflow: hidden;
}

/* Read-only records share one hierarchy: a section heading, one optional
   section-level edit action, then a non-clickable label/value list.  This
   replaces the old customer and reservation row-specific edit affordances. */
.settings-detail-section,
.customer-history-sections .history-section {
  display: grid;
  gap: var(--settings-heading-content-gap);
  margin: 0;
}

.settings-detail-card-group {
  display: grid;
  gap: var(--settings-card-group-gap);
}

/* A detail section may also be used outside ManagementScreen.  The shared
   ManagementScreen content wrapper below removes this local first-child
   offset when it is present, leaving one nav-to-content distance. */
.settings-detail-section:first-child {
  margin-top: var(--settings-heading-gap);
}

.customer-detail-screen,
.reservation-detail-screen,
.item-detail-page {
  display: grid;
  gap: var(--settings-section-gap);
}

/* margin-bottom belongs to the grey-heading contract later in this file. */
.settings-detail-section-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--settings-list-inset);
  min-width: 0;
}

/* Read-only values grow into their available column before wrapping and avoid
   breaking Japanese names or words at arbitrary character boundaries. */
.settings-detail-row > strong,
.reservation-setting-row > strong,
.customer-setting-row > strong,
.maintenance-detail-panel .detail-list > div > dd {
  overflow-wrap: break-word;
  word-break: normal;
  line-break: strict;
  text-wrap: pretty;
}

.settings-detail-section-heading > h2,
.customer-history-sections .history-section > h2 {
  min-width: 0;
  margin: 0;
  padding: 0;
  color: var(--settings-group-title-color);
  font-size: var(--ui-section-title-size);
  font-weight: var(--ui-section-title-weight);
  line-height: var(--ui-section-title-line-height);
}

.settings-detail-section-edit {
  flex: 0 0 auto;
  color: var(--accent);
  font-size: var(--settings-label-size);
  font-weight: 600;
  text-decoration: none;
}

.settings-detail-section-edit:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.settings-detail-list {
  border-top: 0 !important;
}

.customer-directory-empty {
  padding: var(--settings-list-inset) !important;
  color: var(--settings-value-color) !important;
  font-size: var(--settings-value-size) !important;
  font-weight: 400 !important;
  line-height: 1.5;
}

/* Maintenance registration is the same two-column field contract as every
   other settings editor. The full-screen overlay covers its list FAB, and
   its scroll content keeps a shared action-safe tail inset. */
.maintenance-register-overlay {
  padding-bottom: calc(var(--bottom-tabbar-height) + 84px + env(safe-area-inset-bottom)) !important;
}

.maintenance-register-panel .item-form > label:not(.full-span) > select,
.maintenance-register-panel .item-form > label:not(.full-span) > input {
  min-width: 0;
  color: var(--settings-value-color) !important;
  font-size: var(--settings-value-size) !important;
  font-weight: 400 !important;
  text-align: right;
  text-align-last: right;
}

/* The item editor is the same field contract as maintenance registration
   above -- both wrap a plain <form class="form ..."> around this row layout,
   and ".form input/select/textarea" (kasane.css) sets font-size: 15px with no
   competing declaration to beat, so an explicit value is required here too;
   inheriting from the 17px label is not enough once that generic rule
   applies. Maintenance registration got this fix; the item editor and its
   product-name/notes fields did not, which is what read as its value text
   being smaller than every label (P037/P051). */
.item-editor-panel .item-form > label:not(.full-span) > select,
.item-editor-panel .item-form > label:not(.full-span) > input,
.item-editor-panel .item-form .item-identity-row > label > input,
.item-editor-panel .item-form > label.full-span > input,
.item-editor-panel .item-form > label.full-span > textarea {
  color: var(--settings-value-color) !important;
  font-size: var(--settings-value-size) !important;
  font-weight: 400 !important;
}

/* Operation feedback is a dedicated acknowledgement screen, never an
   in-flow banner that shifts the form or scroll position. */
html:has(body.action-result-open),
body.action-result-open,
body.action-result-open .main {
  overflow: hidden;
  overscroll-behavior: none;
}

html:has(body.action-dialog-open),
body.action-dialog-open,
body.action-dialog-open .main {
  overflow: hidden;
  overscroll-behavior: none;
}

html:has(body.action-toast-open),
body.action-toast-open,
body.action-toast-open .main {
  overflow: hidden;
  overscroll-behavior: none;
}

.action-result-screen {
  position: fixed;
  z-index: 1000;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--settings-list-inset);
  background: rgb(60 60 67 / 36%);
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
}

.action-result-card,
.action-dialog-card {
  display: grid;
  width: min(100%, 360px);
  gap: 16px;
  padding: var(--settings-card-padding);
  border-radius: var(--dialog-card-radius);
  background: var(--settings-list-surface);
  box-shadow: none;
  text-align: center;
  touch-action: manipulation;
}

.action-result-card > h2,
.action-result-card > p {
  margin: 0;
  text-align: center;
}

.action-result-card > h2 {
  color: var(--settings-label-color);
  font-size: 19px;
  font-weight: 700;
}

.action-result-card > p {
  color: var(--settings-value-color);
  font-size: var(--settings-value-size);
  font-weight: 400;
  line-height: 1.5;
}

.action-result-card.is-failure > h2 {
  color: var(--danger);
}

.action-result-card .text-link-cta--brand {
  width: 100%;
  min-height: 48px;
  margin-top: 4px;
  border-radius: var(--dialog-button-radius);
  background: var(--accent);
  color: #fff !important;
  font-weight: 600;
}

/* All central confirmation and acknowledgement surfaces share one rhythm. */
.action-dialog-layer {
  position: fixed;
  z-index: 11000;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--settings-list-inset);
  background: rgb(60 60 67 / 36%);
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
}

.action-toast-layer {
  z-index: 1000;
  padding: var(--settings-card-padding);
  background: rgb(60 60 67 / 36%);
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
}

.action-toast {
  width: min(100%, 360px);
  border-radius: var(--settings-list-radius);
  padding: var(--settings-card-padding);
  background: var(--settings-list-surface);
  box-shadow: none;
  color: var(--settings-value-color);
  font-size: var(--settings-value-size);
  font-weight: 400;
  line-height: 1.5;
  text-align: center;
}

.action-dialog-card > h2,
.action-dialog-copy > p {
  margin: 0;
}

.action-dialog-card > h2 {
  color: var(--settings-label-color);
  font-size: 19px;
  font-weight: 700;
}

/* The scan result's note that it closes by itself. */
.action-dialog-copy > p > small {
  display: block;
  margin-top: 8px;
  font-size: 14px;
}

.action-dialog-copy {
  color: var(--settings-value-color);
  font-size: var(--settings-value-size);
  font-weight: 400;
  line-height: 1.5;
}

.action-dialog-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.action-dialog-actions:has(> :only-child) {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
}

.action-dialog-actions--stacked {
  grid-template-columns: minmax(0, 1fr);
}

.action-dialog-actions > button {
  min-height: 48px;
  min-width: 48px;
  border-radius: var(--dialog-button-radius);
}

/* Empty states are explanatory text, not a second card.  This removes every
   legacy dashed outline while retaining each screen's layout-owned spacing. */
.empty-state {
  border: 0 !important;
  border-image: none !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none;
}

/* The white form surface contains only fields.  Every committing action uses
   this shared page-level area below the surface. */
.form-action-area {
  display: grid;
  width: 100%;
  /* Most action areas hold a single button, where this is inert. Where two
     do stack -- the security screen's two red session-revoking buttons, the
     reservation confirm pair -- a grid with no gap butted them together with
     no visual separation at all. */
  gap: var(--settings-selection-control-gap);
  margin-top: var(--settings-section-gap);
}

.form-action-area > .form-action,
.form-action-area > .primary {
  width: 100%;
  margin: 0;
}

.item-editor-form,
.maintenance-register-form,
.return-days-form,
.ledger-operation-form,
.sales-registration-form,
.reservation-form-shell {
  width: 100%;
}

:is(
  .settings-menu .settings-row,
  .management-subpage .settings-row,
  .customer-directory-row,
  .customer-next-row,
  .customer-setting-row,
  .employee-directory-row,
  .employee-editor-row,
  .reservation-setting-row,
  .security-recovery-row,
  .sync-device-panel .management-card,
  .store-settings-form .store-settings-list .store-setting-row,
  .settings-detail-row,
  .maintenance-detail-panel .detail-list > div
) {
  min-height: var(--settings-row-height) !important;
}

:is(
  .settings-row-value,
  .customer-setting-row > strong,
  .store-settings-read-row > strong,
  .store-settings-navigation-row > strong,
  .store-settings-form .store-editable-control input:where(:not(.value-pill, .value-pill-control)),
  .store-settings-form .store-editable-control select:where(:not(.value-pill, .value-pill-control)),
  .employee-directory-row .employee-status,
  .employee-directory-row .employee-directory-meta,
  .employee-editor-row input:where(:not(.value-pill, .value-pill-control)),
  .employee-editor-row select:where(:not(.value-pill, .value-pill-control)),
  .reservation-setting-row > strong,
  .settings-detail-row > strong,
  .maintenance-detail-panel .detail-list > div > dd,
  .security-recovery-row > span:last-child,
  .sync-device-panel .management-card small
) {
  color: var(--settings-value-color) !important;
  font-size: var(--settings-value-size) !important;
  font-weight: 400 !important;
  text-align: right;
}

/* Native select controls need text-align-last as well as text-align for the
   currently selected value to reach the trailing edge in Safari.  This is a
   shared contract for every two-column label/value field editor; it avoids
   per-screen offsets while leaving full-form and multi-select controls alone. */
:is(
  .employee-editor-row > select,
  .store-settings-form .store-editable-control select:where(:not(.value-pill, .value-pill-control)),
  .customer-field-editor form > label > select:not(.value-pill),
  .reservation-field-editor form > label > select:not(.value-pill)
):not([multiple]) {
  text-align: right !important;
  text-align-last: right;
}

:is(
  .settings-menu .settings-row,
  .management-subpage .settings-row,
  .settings-card > .settings-row,
  .customer-directory-row,
  .customer-next-row,
  .customer-setting-row,
  .employee-directory-row,
  .employee-editor-row > span,
  .reservation-setting-row > span,
  .security-recovery-row,
  .sync-device-panel .management-card,
  .store-settings-form .store-settings-list .store-setting-row,
  .settings-field-editor .store-settings-list .store-setting-row,
  .settings-detail-row > span,
  .maintenance-detail-panel .detail-list > div > dt
) {
  color: var(--settings-label-color);
  font-size: var(--settings-label-size) !important;
  font-weight: var(--ui-row-label-weight) !important;
  line-height: var(--ui-row-label-line-height) !important;
}

/* Employee management is a settings-list consumer as well.  Unlike the
   other lists it previously placed its row padding directly on the rows and
   left the white surface with no breathing room.  Keep a single source of
   truth for the inset: the surface owns the card padding, while its rows
   align to that inset and draw their dividers inside it. */
.employee-directory-list,
.employee-editor-list {
  padding: var(--settings-list-inset) !important;
}

.employee-directory-row,
.employee-editor-row,
.employee-editor-notes {
  padding-inline: 0 !important;
}

.employee-directory-row:not(:last-child)::after,
.employee-editor-row:not(:last-child)::after,
.employee-editor-notes:not(:last-child)::after {
  right: 0;
  left: 0;
}

/* Older screens still have border-bottom declarations.  The shared divider
   token wins over those legacy colors and remains neutral on a solid surface. */
.reservation-setting-row:not(:last-child) {
  border-bottom: var(--settings-divider-width) solid var(--settings-divider-color) !important;
}

.reservation-setting-row:last-child {
  border-bottom: 0 !important;
}

/* Keep the empty-state sentence on meaning boundaries rather than allowing a
   single Japanese character to wrap by itself on narrow screens. */
.maintenance-empty-message > span {
  display: block;
}

@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .brand-background__shape {
    filter: blur(56px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .brand-background__shape {
    filter: blur(48px);
  }
}

/* Final shared-form overrides: legacy page rules used right-aligned native
   selects, which clips labels in the maintenance and item editors. */
.maintenance-register-panel .item-form > label > select,
.maintenance-register-panel .item-form > label > input,
.item-editor-panel .item-form > label > select,
.item-editor-panel .item-form > label > input,
.item-editor-panel .item-form > label > textarea {
  box-sizing: border-box !important;
  inline-size: 100% !important;
  min-inline-size: 0 !important;
  max-inline-size: 100% !important;
  text-align: left !important;
  text-align-last: left !important;
}

/* No customer-only chevron placement here. These rows carried a duplicated
   pair of rules centring the glyph inside the disclosure column, which no
   other row family does, so the same chevron sat 26px from the card edge
   while every other screen put it at 32px. The rows now take the shared
   default (P055). */

/* A ledger is one full-width route surface on phones. All four operation
   tabs share this layout; explicitly stretching the final route hierarchy
   prevents a remounted flex child from falling back to its intrinsic card
   width on iOS. Keep this at the route level, not individual lists. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .shell:has(.ledger-phase-stack),
  .main:has(.ledger-phase-stack),
  .main:has(.ledger-phase-stack) .page-transition,
  .main:has(.ledger-phase-stack) .page-transition > .ledger-page-title,
  .main:has(.ledger-phase-stack) .ledger-phase-stack,
  .main:has(.ledger-phase-stack) .tab-content {
    box-sizing: border-box;
    inline-size: 100%;
    min-inline-size: 0;
    max-inline-size: none;
    align-self: stretch;
  }
}

/* Editable management forms share the same list surface as read-only detail
   lists. The card owns its inset; each row draws its separator inside that
   inset. Do not use border-bottom on a row here: that is what caused the
   customer editor's rules to reach the card edges. */
.settings-editable-list {
  overflow: hidden;
}

.settings-editable-list > .settings-editable-group {
  position: relative;
  display: grid !important;
  grid-template-columns: minmax(0, 1fr) !important;
  gap: 0 !important;
  min-width: 0;
}

.settings-editable-list > .settings-editable-row,
.settings-editable-list > .settings-editable-group > .settings-editable-row {
  position: relative;
  display: grid !important;
  grid-template-columns: var(--settings-label-value-columns) !important;
  align-items: center;
  gap: var(--settings-row-content-gap);
  min-height: var(--settings-row-height) !important;
  margin: 0 !important;
  padding: var(--settings-row-padding-block) 0 !important;
  border: 0 !important;
  color: var(--settings-label-color);
}

/* A date plus time needs the whole card width at 390px. Keep it a shared
   editable row, with its label above rather than shrinking the date capsule. */
.settings-editable-list > .settings-editable-row--stacked,
.settings-editable-list > .settings-editable-group > .settings-editable-row--stacked {
  grid-template-columns: minmax(0, 1fr) !important;
}

.settings-editable-list > .settings-editable-row:not(:last-child)::after,
.settings-editable-list > .settings-editable-group > .settings-editable-row:not(:last-child)::after,
.settings-editable-list > .settings-editable-group:not(:last-child)::after {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: var(--settings-divider-width);
  background: var(--settings-divider-color);
  content: "";
}

/* Detail rows use the same label/value grid when an individual edit action is
   available. The disclosure remains an accessory, never a third value column. */
.settings-detail-row.is-editable {
  grid-template-columns: var(--settings-label-value-columns) auto;
  color: inherit;
  text-decoration: none;
}

.settings-detail-row.is-editable > i {
  grid-column: 3;
  color: var(--settings-divider-color);
  font-size: 16px;
}

.settings-detail-row.is-editable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* P028: one card, summary-row, and header rhythm contract.  These are placed
   after legacy screen rules so individual historical patches cannot win the
   cascade over the shared component classes. */
:is(.settings-card--list, .settings-editable-list, .settings-detail-list, .employee-directory-list, .customer-directory-list, .security-recovery-list) {
  background: var(--settings-list-surface) !important;
  border-radius: var(--settings-list-radius) !important;
  box-shadow: none;
}

/* Employee directory rows already own their content height. A surface inset
   is horizontal only, so it cannot create a second, oversized top/bottom
   breathing space around the first and last employee. */
.employee-directory-list {
  padding-block: 0 !important;
  padding-inline: var(--settings-list-inset) !important;
}

.settings-inline-value-row {
  display: flex !important;
  min-inline-size: 0;
  align-items: baseline;
  gap: 6px;
  color: var(--ink);
  font-size: 13px;
  line-height: 1.4;
}

.settings-inline-value-row > b {
  flex: 0 0 auto;
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
}

.settings-inline-value-row > span {
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ledger-record-details > .settings-inline-value-row {
  display: flex !important;
}

/* A value column must be allowed to shrink before its disclosure accessory.
   The same rule serves the security page and store navigation rows. */
:is(.security-settings-row, .settings-navigation-row, .store-settings-navigation-row) {
  min-inline-size: 0;
}

/* The security page's value column wraps instead of clipping (P048): the
   label column is now the fixed side (see .security-settings-row's grid in
   kasane.css), so the value can safely spend its remaining width on a
   second line rather than silently truncating with an ellipsis. */
:is(.security-settings-row, .settings-navigation-row) > .settings-row-value {
  min-inline-size: 0;
  max-inline-size: 100%;
  overflow-wrap: anywhere;
  text-align: right;
}

.store-settings-navigation-row > strong {
  min-inline-size: 0;
  /* The ceiling lives on the track (fit-content(58%) in kasane.css), not
     here: a percentage max-inline-size resolves against the value's own
     grid area, so it shrank the value inside an already content-sized
     track rather than bounding it (P060). */
  max-inline-size: 100%;
  overflow: hidden;
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Keep every thumbnail's backing surface clipped to its declared rounded
   rectangle. The no-image hanger can therefore never reveal a square layer. */
.inventory-thumb {
  overflow: hidden !important;
  border-radius: var(--inventory-thumbnail-radius, var(--radius-sm)) !important;
  /* Only visible behind the no-image hanger: that placeholder sits on the
     same white card surface as every other tile, not on a grey swatch. */
  background: var(--paper);
}

/* A photo is its own edge; only the no-image tile, white on the white card,
   keeps the grey outline that shows where it is (2026-09-27). */
.inventory-thumb:has(> .inventory-thumb-image) {
  border: 0;
}

.inventory-thumb-image {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

/* ManagementScreen owns the one gap between its fixed header and the first
   group. Its scroll viewport has no top padding; a dedicated inner wrapper
   makes the same token apply whether a route passes a subpage, a form, or a
   detail section directly. */
.management-screen-scroll {
  padding-block-start: 0;
}

.management-screen-content {
  min-inline-size: 0;
  padding-block-start: var(--management-content-start-gap);
}

.management-screen-content > .settings-detail-section:first-child,
.management-screen-content > .management-subpage > .settings-detail-section:first-child {
  margin-block-start: 0;
}

/* P029: the app canvas, white-card inset, and grouped-heading rhythm are
   global contracts.  They deliberately come last so that historical route
   patches cannot reintroduce the former lavender canvas or one-off card
   padding values. */
.settings-card--padded {
  padding: var(--settings-card-padding);
}

.settings-card--compact-padded {
  padding: var(--settings-card-compact-padding);
}

/* One-field detail editors share one surface and one action placement.
   Legacy product, customer, and reservation routes now compose this piece
   instead of each owning a subtly different card and save-button layout. */
.settings-field-editor {
  width: 100%;
}

.settings-field-editor > form {
  display: grid;
  gap: 0;
}

.settings-field-editor-surface {
  overflow: hidden;
  padding: 0 !important;
}

.settings-field-editor-surface > label {
  position: relative;
  display: grid;
  grid-template-columns: var(--settings-label-value-columns);
  align-items: center;
  gap: var(--settings-row-content-gap);
  min-height: var(--settings-row-height);
  padding: var(--settings-row-padding-block) var(--settings-list-inset);
  color: var(--settings-label-color);
  font-size: var(--ui-row-label-size);
  font-weight: var(--ui-row-label-weight);
}

.settings-field-editor-surface > label + label::before {
  position: absolute;
  top: 0;
  right: var(--settings-list-inset);
  left: var(--settings-list-inset);
  height: var(--settings-divider-width);
  background: var(--settings-divider-color);
  content: "";
}

.settings-field-editor-surface > label > input:where(:not(.value-pill, .value-pill-control)),
.settings-field-editor-surface > label > select:where(:not(.value-pill, .value-pill-control)),
.settings-field-editor-surface > label > textarea {
  min-width: 0;
  min-height: 40px;
  border: 0 !important;
  border-radius: 0;
  background: transparent !important;
  box-shadow: none;
  /* Entered text is primary content; secondary grey belongs to static
     trailing values and placeholders, not the value being edited. */
  color: var(--settings-label-color);
}

.settings-field-editor-surface > label > input,
.settings-field-editor-surface > label > select {
  padding-inline: 12px;
  text-align: right;
}

.settings-field-editor-surface > label > textarea,
.settings-field-editor-surface > label > select[multiple] {
  min-height: 112px;
  padding: 10px 12px;
}

.settings-field-editor-surface > label > textarea {
  grid-column: 2;
  resize: vertical;
}

.settings-field-editor-actions {
  margin-top: var(--settings-section-gap);
}

/* A form can supply the native input contract without also becoming a second
   padded surface.  Content inside a SettingsCard must take its edge rhythm
   from that shared card, never from the legacy .form's 24px inset. */
.form.form--surfaceless {
  width: 100%;
  padding: 0;
}

/* Detail inventory is a three-region record: thumbnail, identity, then the
   status summary. Older screen patches left those grid positions implicit,
   so an intrinsic photo could compete with the text region on phones. The
   shared inventory contract owns both the grid placement and its insets. */
.inventory-mode-detail .inventory-image-link,
.inventory-mode-detail .inventory-thumb {
  min-inline-size: 0;
  max-inline-size: 100%;
}

.inventory-thumb-image {
  max-inline-size: 100%;
}

@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .inventory-page .inventory-mode-detail {
    --inventory-detail-columns: var(--inventory-detail-image-size) minmax(0, 1fr) var(--inventory-status-width);
  }

  .inventory-page .inventory-mode-detail .inventory-image-link {
    grid-column: 1 !important;
    grid-row: 1;
  }

  .inventory-page .inventory-mode-detail .inventory-card-main {
    grid-column: 2 !important;
    grid-row: 1;
    min-inline-size: 0 !important;
    padding-inline-end: 0 !important;
  }

  .inventory-page .inventory-mode-detail .inventory-card-status-box {
    position: static !important;
    grid-column: 3 !important;
    grid-row: 1;
    align-self: start;
    justify-self: end;
    width: var(--inventory-status-width) !important;
    margin: 0 !important;
  }

  .inventory-page .inventory-mode-detail .inventory-card-status-box > span {
    padding-inline: var(--inventory-card-pad);
  }
}

/* Canonical white application surfaces.  Components that carry their own row
   insets keep those rows; loose-content cards use only large or small. */
:is(
  .settings-card--list,
  .settings-card--panel,
  .settings-card--compact,
  .settings-editable-list,
  .settings-detail-list,
  .settings-menu .settings-list,
  .management-subpage .settings-list,
  .customer-directory-list,
  .customer-settings-list,
  .customer-next-section,
  .history-box,
  .employee-directory-list,
  .employee-editor-list,
  .audit-filter-surface,
  .audit-log-list,
  .security-recovery-list,
  .sync-device-panel .management-card-list,
  .csv-feature-group > .csv-box,
  .store-settings-form .store-settings-group .store-settings-section,
  .reservation-settings-list,
  .maintenance-detail-panel .detail-list
) {
  box-shadow: none;
}

.card {
  padding: var(--card-padding-large);
}

/* Dense inventory records are the small-card exception; each side receives
   exactly the same inset in both list and detailed inventory modes. */
/* contract:grey-heading:start */
/* ===========================================================================
   GREY SECTION HEADING CONTRACT -- the single source of the heading-to-content
   gap.  Do not restate margin/padding for a heading, its container, or the
   element after it anywhere else; scripts/check-layout-contract.mjs fails the
   build when a rule tries.

   Three things can push content away from a heading, so all three are pinned
   here rather than screen by screen:
     1. the heading's own margin-bottom -- the one real gap,
     2. the container's `gap`, which would stack on top of it,
     3. the following element's margin-top, which would stack as well.

   2 and 3 are matched structurally (":has(> heading)" and "heading + *"), not
   by listing the screens that happen to exist today.  The previous revision
   enumerated fifteen container classes, so every screen added afterwards
   silently reintroduced a doubled gap -- three separate regressions before
   this rule replaced the list (P049).
   =========================================================================== */
.settings-section-heading,
:is(
  .store-settings-section-title,
  .customer-section-heading,
  .employee-directory-heading,
  .employee-editor-heading,
  .audit-section-heading,
  .history-section > h2,
  .customer-detail-section > h2,
  .customer-form-screen .form-group-section > h2,
  .management-screen-scroll .form-group-section > h2
) {
  min-height: 0 !important;
  margin: 0 0 var(--settings-heading-content-gap) !important;
  padding-inline: var(--settings-heading-inline-inset) !important;
}

/* (2) Any container holding a heading delegates the gap to the heading. This
   matches on structure instead of naming containers: the class list it
   replaced had to be extended by hand for every new screen. */
:has(> .settings-section-heading) {
  gap: 0 !important;
}

/* (3) Whatever follows a heading contributes no margin of its own. */
.settings-section-heading + * {
  margin-top: 0 !important;
}

/* (4) Rule (2) also took the space between two white cards in one group: a
   list under its filters (操作履歴) or under its search field (お客様一覧)
   sat flush against it (2026-09-27). A card that follows another card keeps
   the space between cards; one under a search field keeps the heading's
   space, since the field heads the list it filters.
   Only inside a group that holds a heading, whose gap (2) zeroed: a list of
   cards with its own gap (the inventory cards, 8px) took the 35px on top of
   it and its items stood 43px apart (2026-09-27). */
:has(> .settings-section-heading) > .settings-card + .settings-card {
  margin-top: var(--settings-section-gap);
}

:has(> .settings-section-heading) > .management-search-row + .settings-card {
  margin-top: var(--settings-heading-content-gap);
}

/* (4) Because (2) zeroes the container gap, consecutive heading-led groups
   inside a container that holds a heading of its own would otherwise touch.
   They keep the section rhythm, which is a different value from the
   heading-to-content gap -- one `gap` cannot express both, so the group
   spacing is a margin between siblings.  This never fights (3): the first
   group follows the heading, not another group.
   It reaches only those zeroed containers.  A container without a heading of
   its own is a section stack whose gap is already the section gap, and a
   margin there stacked on top of it: the menu read 47px from a card to the
   next grey title where the ledger read 35px (2026-09-27). */
:has(> .settings-section-heading) > :has(> .settings-section-heading) + :has(> .settings-section-heading) {
  margin-top: var(--settings-section-gap) !important;
}

/* (5) is retired (2026-09-24). It gave every element after a heading's
   first content element the 10px heading gap. P052 (6a6cc85, 2026-09-17)
   appended a sentence after this comment's closing marker, so the sentence
   became part of the selector and browsers dropped the whole rule: it has
   not applied since. The spacing it covered is now owned by rules written
   against that reality -- the card footnote gap (8px), the flat-form
   section gap below, and .form-action-area's own margin -- and turning it
   back on would regress them (measured: the role-label and employee
   editors' save button would move from 35px to 10px under its card). */

/* Flat forms. When a form lists its sections as siblings (heading, card,
   heading, card) rather than one container per section, a later heading sat
   directly under the card before it (0px; contract (5) above was already
   not applying), so the employee editor's 権限の個別設定 and 信頼済み端末
   read as part of the section above. A heading that follows
   other content opens a new section and takes the section gap; after a
   footnote, the footnote-to-section gap. Groups that follow another
   heading-led group keep contract (4). Prefixed with the scroll container
   because the heading contract's own :is() list carries a
   ".management-screen-scroll .form-group-section > h2" argument, which lends
   the whole margin: 0 rule that specificity. */
.management-screen-scroll .settings-section-heading + * ~ .settings-section-heading,
.management-screen-scroll .settings-section-heading + * ~ :not(:has(> .settings-section-heading)) + :has(> .settings-section-heading) {
  margin-top: var(--settings-section-gap) !important;
}

.management-screen-scroll .settings-section-heading + * ~ :is(.settings-menu-detail, .settings-helper) + :is(.settings-section-heading, :has(> .settings-section-heading)) {
  margin-top: var(--settings-footnote-section-gap) !important;
}
/* A list's grey heading under the purple band (ScopeBand) starts a new
   section, as after any other content (操作履歴, 2026-10-14). */
.management-screen-scroll .scope-band + .settings-section-heading {
  margin-top: var(--settings-section-gap) !important;
}
/* contract:grey-heading:end */

.settings-section-heading {
  display: flex;
  min-inline-size: 0;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--settings-list-inset);
}

/* Every existing caller's title and action are short enough that this never
   mattered, but a longer pair (P057: a heading's title alongside a
   descriptive note, not just an icon or a short count) squeezes both into
   roughly half the card width. Japanese text has no word-boundary
   requirement, so each half then wraps character-by-character rather than
   overflowing -- it reads as a mid-word break ("ログイン" as "ログイ"/"ン").
   .panel-head, the older per-screen equivalent of this heading, already
   solves this by stacking title above action below 480px; give the shared
   component the same fallback so any future long title+action pairing gets
   it automatically instead of rediscovering the bug per screen. */
@media (max-width: 480px) {
  .settings-section-heading {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }
}

/* Both Home schedules reserve a predictable three-row viewport. The 48px
   card bars and a tighter 在庫状況 leave room for the third row. A fourth
   appointment scrolls within its own list rather than changing the
   dashboard layout. */
.home-schedule-panel .timeline-list,
.home-schedule-panel .week-list {
  box-sizing: border-box;
  min-height: var(--home-schedule-list-height) !important;
  padding-block: var(--home-schedule-list-inset-block) !important;
}

@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  /* 在庫状況 (the third row) is as tall as its two rows of counts. As an
     auto row it could shrink below them, since the card hides overflow, and
     its second row was cut in half on a phone (2026-09-27); now the page
     scrolls the last pixels instead. */
  .home-dashboard {
    grid-template-rows: auto max-content max-content auto !important;
  }

  .home-schedule-sections {
    grid-template-rows: auto 1px auto !important;
  }

  .home-schedule-section {
    grid-template-rows: auto var(--home-schedule-list-height) auto !important;
  }

  .home-schedule-scroll {
    block-size: var(--home-schedule-list-height);
    max-height: var(--home-schedule-list-height);
    overflow-y: auto;
  }
}

/* On a short phone, keeping the 48px headings and both 48px actions requires
   a smaller gap between the four home blocks. Their contents stay unchanged. */
@media (max-width: 767.98px) and (max-height: 880px), (hover: none) and (pointer: coarse) and (max-height: 880px) {
  .home-dashboard {
    gap: 8px;
  }
}

/* Ledger records are shared compact cards. A thin line is the visual boundary
   between adjacent reservations, checkouts, returns, and sales. */
.ledger-record-card {
  border: 1px solid var(--line) !important;
}

/* The reusable dense label/value pair owns a readable label-to-value gap.
   It serves every operational card, including reservation customer names. */
.settings-inline-value-row {
  column-gap: 8px !important;
}

.settings-section-heading > h2,
:is(
  .store-settings-section-title,
  .customer-section-heading,
  .employee-directory-heading,
  .employee-editor-heading,
  .audit-section-heading
) > h2 {
  min-inline-size: 0;
  margin: 0;
  padding: 0 !important;
  color: var(--settings-group-title-color);
  font-size: var(--ui-section-title-size);
  font-weight: var(--ui-section-title-weight);
  line-height: var(--ui-section-title-line-height);
}

/* Store setting values describe actual data. Unlike short navigation values,
   they wrap at safe Japanese word boundaries instead of being ellipsized. */
.store-settings-navigation-row > strong,
.store-settings-read-row > strong {
  min-inline-size: 0;
  max-inline-size: 100%;
  overflow: visible;
  text-align: right;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* P037 — canonical corrections for the item editor and detail inventory
   card. Shared field-editor declarations live together above. */
.item-editor-panel .item-form > label:not(.full-span) > select,
.item-editor-panel .item-form > label:not(.full-span) > input:not([type="hidden"]):not([type="file"]) {
  text-align: right !important;
  text-align-last: right !important;
}

.image-replace-trigger {
  position: relative;
  cursor: pointer;
  overflow: hidden;
}

/* The 写真を変更 caption only; the empty-slot placeholder is a span too. */
.image-replace-trigger > span:not(.image-placeholder) {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  padding: 4px;
  background: rgb(0 0 0 / .56);
  color: #fff;
  font-size: 10px;
  line-height: 1.2;
  text-align: center;
  z-index: 1;
}

.image-replace-input {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .inventory-page .inventory-mode-detail .inventory-card-status-box > span:not(:last-child) {
    border-bottom: 1px solid var(--line) !important;
  }
}

.home-schedule-section .home-schedule-more {
  position: static;
  z-index: 2;
  min-block-size: 20px;
  margin: 0 var(--settings-list-inset) 4px;
  padding: 2px 0;
  line-height: 16px;
  text-align: center;
}

/* Home schedule content has a separate compact density from settings lists,
   but its heading, rows, divider, and continuation marker still share one
   parent-owned edge.  Child elements must not compensate with local insets. */
.home-schedule-panel {
  --home-schedule-inline-inset: 10px;
}

.home-schedule-panel .compact-schedule-row {
  padding-inline: var(--home-schedule-inline-inset) !important;
}

.home-schedule-panel .timeline-list,
.home-schedule-panel .week-list {
  row-gap: var(--home-schedule-row-gap) !important;
}

.home-schedule-panel .home-schedule-divider {
  margin-inline: var(--home-schedule-inline-inset) !important;
}

.home-schedule-section .home-schedule-more {
  margin-inline: var(--home-schedule-inline-inset) !important;
}

/* P039: iOS Settings light-mode geometry.  These semantic tokens are shared
   by every settings/detail consumer; routes may not substitute local offsets
   or alternative card treatments. */
/* The page gutter is the card edge.  A card's own 20px inset places its
   primary text on the 40px visual grid. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .management-screen-scroll,
  .management-screen-content,
  .store-settings-form,
  .item-master-settings {
    --page-gutter: var(--settings-page-inset);
  }
}

.settings-card--list,
.settings-detail-list,
.settings-editable-list,
.ledger-record-list,
.item-master-panel,
.item-master-values {
  border: 0 !important;
  border-radius: var(--settings-list-radius) !important;
  background: var(--list-card) !important;
  box-shadow: none;
}

.settings-section-heading > h2,
.settings-detail-section-heading > h2,
.store-settings-section-title > h2,
.management-settings-group > h2 {
  color: var(--list-secondary-label) !important;
  font-size: var(--ui-section-title-size) !important;
  font-weight: var(--ui-section-title-weight) !important;
  line-height: var(--ui-section-title-line-height) !important;
}

/* These hold a bare <h2> rather than the shared heading component, so the
   grey-heading contract's ":has(> .settings-section-heading)" cannot reach
   them; they opt into the same no-container-gap rhythm explicitly. */
.customer-history-sections .history-section,
.store-settings-form .store-settings-group,
.item-master-form-section {
  gap: 0 !important;
}

.customer-detail-screen,
.reservation-detail-screen,
.item-detail-page,
.store-settings-form,
.ledger-phase-stack .tab-content {
  gap: var(--settings-section-gap) !important;
}

.settings-detail-row,
.settings-editable-list > .settings-editable-row,
.settings-editable-list > .settings-editable-group > .settings-editable-row {
  min-height: var(--settings-row-height) !important;
  color: var(--list-label) !important;
  font-size: var(--ui-row-label-size) !important;
  font-weight: var(--ui-row-label-weight) !important;
  line-height: var(--ui-row-label-line-height) !important;
}

.settings-detail-row {
  padding-inline: var(--settings-list-inset) !important;
}

.settings-detail-row:not(:last-child)::after {
  right: var(--settings-list-inset) !important;
  left: var(--settings-list-inset) !important;
  background: var(--list-separator) !important;
}

/* Same separator colour, but these rows carry no inline padding of their own
   (padding: 8px 0 above), so their label already sits on the row's edge. They
   were grouped with .settings-detail-row, which does inset its content, and
   inherited its --settings-list-inset -- leaving every divider on the employee
   editor starting 20px to the right of the label it belongs under. */
.settings-editable-list > .settings-editable-row:not(:last-child)::after,
.settings-editable-list > .settings-editable-group > .settings-editable-row:not(:last-child)::after {
  right: 0 !important;
  left: 0 !important;
  background: var(--list-separator) !important;
}

.settings-detail-row > strong,
.store-settings-navigation-row > strong,
.store-settings-read-row > strong,
.settings-detail-row.is-editable > i,
.store-settings-navigation-row > i {
  color: var(--list-secondary-label) !important;
}

.settings-detail-row.is-editable > i,
.store-settings-navigation-row > i {
  color: var(--list-chevron) !important;
}

.settings-menu-detail {
  margin-top: var(--settings-card-footnote-gap) !important;
  padding-inline: var(--settings-list-inset) !important;
  color: var(--list-secondary-label) !important;
  font-size: var(--settings-footnote-size) !important;
  font-weight: 400 !important;
  line-height: var(--settings-footnote-line-height) !important;
}

/* In a detail section a footnote is followed by its own card (売上の集計's
   「その他の集計」 link): the shared footnote-to-next-block gap, as under a
   footnote before a heading, instead of the card touching the text. */
.settings-detail-section > .settings-menu-detail + :not(.settings-section-heading) {
  margin-top: var(--settings-footnote-section-gap);
}

/* A footnote's own line box makes the next heading appear 32px away. */
.store-settings-form .store-settings-group:has(.settings-menu-detail) + .store-settings-group {
  margin-top: calc(var(--settings-footnote-section-gap) - var(--settings-section-gap)) !important;
}

.settings-switch {
  inline-size: var(--settings-switch-width) !important;
  block-size: var(--settings-switch-height) !important;
  border-radius: calc(var(--settings-switch-height) / 2) !important;
}

.settings-switch::after {
  inset: var(--settings-switch-inset) auto var(--settings-switch-inset) var(--settings-switch-inset) !important;
  inline-size: var(--settings-switch-thumb-width) !important;
  block-size: var(--settings-switch-thumb-height) !important;
  border-radius: calc(var(--settings-switch-thumb-height) / 2) !important;
}

.settings-switch[aria-checked="true"]::after {
  transform: translateX(calc(var(--settings-switch-width) - var(--settings-switch-thumb-width) - (var(--settings-switch-inset) * 2))) !important;
}

.settings-toggle-row .store-editable-control {
  display: grid;
  align-items: center;
  justify-items: end;
  min-width: var(--settings-switch-width);
}

/* Tags are a settings flow: store selection is one disclosure row, kinds are
   a lightweight strip, and add/edit/list surfaces are grouped cards. */
.item-master-settings {
  gap: var(--settings-section-gap) !important;
}

/* R17: under a choice whose list is still empty, the way to タグ設定 on a
   line of its own across the whole row, the link in the brand colour. */
/* P8: a returning customer's notes and last use, one line each. */
.customer-memo-notice > span {
  display: block;
}

.empty-choices-link > a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.item-master-settings > .field-help {
  margin: 0 !important;
  padding-inline: var(--settings-list-inset);
  color: var(--list-secondary-label);
  font-size: var(--settings-footnote-size);
  line-height: var(--settings-footnote-line-height);
}


/* One row, at the inventory filter strip's own size. Eight kinds in a
   four-column grid took two rows and stood twice as tall as the strip of
   chips it mirrors on the inventory screen, at 15px against that strip's
   12px. A sideways strip keeps every kind reachable without the card
   growing a second row (P060). */
/* The eight kinds sit in two rows of four, all at once: in one scrolling row
   a phone showed only up to サイズ and hid the rest (2026-09-27). Every cell
   is the same width, so the selected pill is the same size whichever kind
   it marks. */
.item-master-kind-tabs {
  display: grid !important;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--settings-selection-control-gap) !important;
  overflow-x: hidden !important;
  overflow-y: hidden !important;
  /* none, not contain: contain leaves the strip free to bounce on its own. */
  overscroll-behavior: none;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none;
  padding: 0 var(--settings-list-inset) !important;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.item-master-kind-tabs::-webkit-scrollbar {
  display: none;
}

.segmented-pills > button {
  box-sizing: border-box;
  inline-size: 100%;
  min-inline-size: 0;
  /* The inventory filter chip's own height and text size. */
  height: 36px;
  min-height: 36px;
  border: 0 !important;
  /* Same fully-round pill as the inventory view-mode toggle, which is the
     app's reference shape for a segmented selector. */
  border-radius: 999px !important;
  background: transparent !important;
  color: var(--list-secondary-label) !important;
  font-size: 12px;
  font-weight: 500;
  padding-inline: 4px;
  white-space: nowrap;
  transition: color 200ms ease-out;
}

.segmented-pills > button.is-selected {
  color: var(--paper) !important;
  font-weight: 600;
}

.segmented-pills:not(.is-sliding) > button.is-selected {
  background: var(--accent) !important;
}

.item-master-form {
  gap: 0 !important;
  padding: 0 !important;
}

.item-master-panel > label,
.item-master-value-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
  align-items: center;
  min-height: var(--settings-row-height);
  gap: 12px;
  margin: 0 !important;
  padding: 0 var(--settings-list-inset) !important;
  color: var(--list-label);
  font-size: 17px;
  font-weight: 400;
  line-height: 22px;
}

.item-master-panel > label:not(:last-of-type)::after,
.item-master-value-row:not(:last-child)::after {
  position: absolute;
  right: var(--settings-list-inset);
  bottom: 0;
  left: var(--settings-list-inset);
  block-size: 1px;
  background: var(--list-separator);
  content: "";
}

.item-master-panel > label > input {
  min-width: 0;
  min-height: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none;
  padding: 0 !important;
  color: var(--list-secondary-label);
  text-align: right;
}

.item-master-values {
  overflow: hidden;
}

.item-master-value-row {
  grid-template-columns: minmax(0, 1fr) auto;
}

.item-master-value-row + .item-master-value-row {
  border: 0 !important;
}

.item-master-value-actions .button.danger {
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  color: var(--danger) !important;
  padding: 6px 2px !important;
}

/* Ledger reservations are a single grouped card.  The prior compact cards
   nested white/bordered cards inside another white panel; adjacent records
   now use one inset separator, including the calendar's selected records. */

.ledger-phase-stack .management-settings-group + .management-settings-group {
  margin-top: var(--settings-section-gap) !important;
}

.ledger-record-list {
  display: block !important;
  overflow: hidden;
  /* Rows carry their own inline inset. The block inset is the list's, and it
     matches a row's own block padding so the space above the first row and
     below the last one equals the space either side of a divider -- with
     padding 0 the last row sat half as far from the card edge as it did from
     its neighbour (P049). */
  padding: var(--card-padding-small) 0 !important;
}

.ledger-record-card {
  position: relative;
  display: grid !important;
  padding-inline: var(--settings-list-inset) !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none;
}

.ledger-record-card:not(:last-child)::after {
  position: absolute;
  right: var(--settings-list-inset);
  bottom: 0;
  left: var(--settings-list-inset);
  block-size: 1px;
  background: var(--list-separator);
  content: "";
}

.ledger-record-chevron {
  inset-inline-end: var(--settings-list-inset);
}

/* Home schedule: the two sections are one compact card system. Count badges,
   divider, and list cards share one 10px horizontal edge; each list owns the
   same 10px top and bottom inset so neither section can gain spare space. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .home-schedule-panel {
    --home-schedule-inline-inset: 10px;
    --home-schedule-list-inset-block: 10px;
    --home-schedule-section-heading-height: 36px;
    --home-schedule-section-height: calc(var(--home-schedule-section-heading-height) + var(--home-schedule-list-height));
    --home-schedule-sections-height: calc((var(--home-schedule-section-height) * 2) + 1px);
    grid-template-rows: var(--home-card-head-height) auto !important;
    block-size: calc(var(--home-card-head-height) + var(--home-schedule-sections-height));
    min-block-size: calc(var(--home-card-head-height) + var(--home-schedule-sections-height));
  }

  .home-schedule-sections {
    block-size: var(--home-schedule-sections-height);
    grid-template-rows: var(--home-schedule-section-height) 1px var(--home-schedule-section-height) !important;
  }

  .home-schedule-section {
    grid-template-rows: var(--home-schedule-section-heading-height) var(--home-schedule-list-height) auto !important;
  }

  /* Only the scrolling frame has the fixed height. The list inside it was
     capped to the same height, so the frame could scroll only as far as
     the list's overflow and the last row stayed half hidden (2026-09-27);
     the list now grows with its rows and at least fills the frame. */
  .home-schedule-panel .home-schedule-scroll {
    box-sizing: border-box;
    block-size: var(--home-schedule-list-height);
    min-block-size: var(--home-schedule-list-height) !important;
    max-block-size: var(--home-schedule-list-height);
  }

  .home-schedule-panel .timeline-list,
  .home-schedule-panel .week-list {
    box-sizing: border-box;
    block-size: auto;
    min-block-size: var(--home-schedule-list-height);
    max-block-size: none;
  }

  .home-schedule-panel .timeline-list,
  .home-schedule-panel .week-list {
    padding-block: var(--home-schedule-list-inset-block) !important;
    padding-inline: var(--home-schedule-inline-inset) !important;
    /* The section heading is a fixed-height box that centres its label, so it
       already owns the space under "今日"/"今週". The list's own top inset
       stacked on that and made the gap below each label one inset wider than
       the gap above it. The block inset stays in the height math above; only
       its top contribution is dropped. */
    padding-block-start: 0 !important;
  }

  .home-schedule-panel .schedule-empty-state {
    box-sizing: border-box;
    block-size: 100%;
    min-block-size: 100% !important;
    margin: 0;
    padding: 0;
  }

  .home-schedule-section .home-schedule-more {
    position: absolute;
    inset-block-end: 0;
    inset-inline: var(--home-schedule-inline-inset);
    margin: 0 var(--home-schedule-inline-inset);
  }
}

/* The fee rows carry five and three controls on one line. At phone width that
   never fitted: the cancel row's method select landed on top of the amount
   beside it, and the late-fee row's ran past the card's right edge (measured
   at 390px: 233..393 against a row ending at 350). Giving each row two lines
   lets every control keep a usable width instead of competing for one. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
}

/* A toggle row is a label and a switch -- two things, not the label/value/
   chevron triple the other settings rows lay out. It was inheriting that
   triple, so every notification label was squeezed into a 121px label column
   and wrapped onto two and three lines while the switch sat in a track wider
   than it needed and a 20px chevron track stayed empty (P060). */
.settings-toggle-row {
  grid-template-columns: minmax(0, 1fr) auto;
}

/* 追加ボタンは上の入力欄に属し、下の一覧には属さない。The two gaps around it
   were both --settings-section-gap (35px), so the button floated equidistant
   between what it acts on and what it produces, and it was not obvious which
   list the fields above were adding to (P060). */
.item-master-settings .item-master-form-actions {
  margin-top: var(--settings-heading-content-gap);
}

.item-master-settings .item-master-values {
  margin-top: var(--settings-section-gap);
}

/* 直近の予定 is always three appointments tall, and the rows inside it keep
   their own height. The list was stretching its rows to fill that fixed
   space, so two appointments rendered as two 60px rows rather than three
   36px rows with the third slot empty -- the card never changed height, but
   what it showed did, which is what read as it shrinking (P060). */
.home-schedule-panel .timeline-list,
.home-schedule-panel .week-list {
  align-content: start;
}

.home-schedule-panel .compact-schedule-row {
  height: var(--home-schedule-compact-row-height);
  flex: 0 0 var(--home-schedule-compact-row-height);
}

/* The continuation marker overlays the third row's bottom rule instead of
   sitting below the list: as a static row it pushed the card past the three
   appointments it promises, and it belongs to the row it is cutting off. */
.home-schedule-section {
  position: relative;
}

.home-schedule-section .home-schedule-more {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  margin: 0 var(--home-schedule-inline-inset);
  pointer-events: none;
}

/* The empty message still fills the three-appointment space and centres in
   it; only the rows stop stretching. Its block-size: 100% resolved against
   its own grid row once the list packed to the start, which left the message
   sitting 22px tall at the top of an otherwise empty card. */
.home-schedule-panel .schedule-empty-state {
  display: grid;
  block-size: var(--home-schedule-list-height) !important;
  min-block-size: var(--home-schedule-list-height) !important;
  place-items: center;
}

/* An editable row sits among toggle rows in the same card, so it divides its
   width the same way. Measured at 390px: padding 8px/8px, min-height 54px and
   the 20px divider inset were already identical on both, and the only thing
   that differed was grid-template-columns -- 121px/181px against the toggle
   rows' 239px/63px. The label started at a different width and the control
   claimed three times the room a switch does, which is what read as the
   送信時刻 row not lining up with the switches above and below it (P061). */
.store-settings-form .store-settings-list .store-editable-row {
  grid-template-columns: minmax(0, 1fr) auto;
}

/* A row whose value is a grey capsule (ValueSelect, NumberSelect pill) keeps
   its whole label on one line. The capsule receives the remaining width
   instead of narrowing the label to a few characters; fit-content(50%) cut
   返却遅延の警告タイミング in half (owner, 2026-10-15). The capsule has its own
   maximum width, so a long value still fits beside the label. */
.store-settings-form .store-settings-list .settings-choice-row,
.store-settings-form .store-settings-list .store-editable-row:has(> .store-editable-control > .value-pill-fit) {
  grid-template-columns: max-content minmax(0, 1fr);
}

.settings-choice-row > span:first-child,
.store-settings-form .store-settings-list .store-editable-row:has(> .store-editable-control > .value-pill-fit) > span:first-child {
  white-space: nowrap;
}

/* A row whose value is typed text is the other way round. A text input's own
   width (about 243px at 390px) filled the auto track and squeezed the label
   to 59px, so 電話番号, メールアドレス and 市区町村 broke onto two and three
   lines (基本情報, 2026-09-25). The label keeps its own width, up to half the
   row, and the input takes the rest. Native selects can have long options
   (操作種別, 2026-10-12). */
.store-settings-form .store-settings-list .store-editable-row:has(> .store-editable-control > :is(input:not([type="time"]), select, .postal-inline, .password-input)) {
  grid-template-columns: fit-content(50%) minmax(0, 1fr);
}

/* ...and the control sizes to its value rather than stretching, so the auto
   track above resolves to the value's width instead of the native time
   control's much wider intrinsic size. */
.store-settings-form .store-settings-list .store-editable-control input[type="time"] {
  width: auto;
  max-width: 100%;
}

/* Editable cards own the row inset on the sides only (2026-09-24).
   padding="large" also put 20px above the first row and below the last,
   which no other grouped list has: the role-label screen, the employee
   editor and the customer form each opened and closed with an empty band
   inside the card. Rows already carry their own 8px block padding. */
.settings-card.settings-editable-list {
  padding-block: 0 !important;
}

/* A switch row inside an editable card. The card already insets it, so the
   row's own 20px inset doubled it to 40px (label and switch both pulled
   inward), and its full-width border-bottom drew a rule under the last row.
   It takes the editable rows' separator instead: inside the inset, none on
   the last row. */
.settings-editable-list > .settings-toggle-row {
  position: relative;
  padding-inline: 0 !important;
  border-bottom: 0 !important;
}

.settings-editable-list > .settings-toggle-row:not(:last-child)::after {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: var(--settings-divider-width);
  background: var(--list-separator);
  content: "";
}

/* The explanation under a switch label is prose. It inherited the label's
   keep-all, which only breaks at punctuation, so it broke after every 、
   and ・ instead of filling the line. */
.settings-toggle-row-label > small {
  word-break: normal;
}

/* A .settings-helper placed directly under a card is that card's footnote,
   and reads like every other footnote (.settings-menu-detail): 8px below
   the card, text on the rows' 20px inset, footnote grey. It sat flush
   against the card with a 10px inset, left of the labels above it. The
   detail list and the editable card are white cards too (2026-09-28). */
:is(.settings-card, .settings-editable-list, .security-recovery-list, .settings-detail-list, .store-settings-group, .password-requirements) + .settings-helper {
  margin-top: calc(var(--settings-card-footnote-gap) - var(--footnote-parent-gap, 0px)) !important;
  padding-inline: var(--settings-list-inset) !important;
  color: var(--list-secondary-label) !important;
  font-size: var(--settings-footnote-size) !important;
  line-height: var(--settings-footnote-line-height) !important;
}

/* In a grid whose children sit a gap apart, the footnote still hangs 8px
   under its own card, not the grid's gap plus 8px (2026-09-28). Each grid
   names its gap on the footnote itself, so nothing deeper inherits it. */
.store-settings-form > :is(.settings-card, .settings-editable-list, .security-recovery-list, .settings-detail-list, .store-settings-group, .password-requirements) + .settings-helper,
.store-settings-form > :is(.settings-card, .settings-editable-list, .security-recovery-list, .settings-detail-list, .store-settings-group, .password-requirements) + .password-requirements {
  --footnote-parent-gap: var(--settings-section-gap);
}

/* The password requirements under a password card hang there the same way,
   on the rows' inset, keeping their own size and check colours. */
:is(.settings-card, .settings-editable-list, .security-recovery-list, .settings-detail-list, .store-settings-group) + .password-requirements {
  margin-top: calc(var(--settings-card-footnote-gap) - var(--footnote-parent-gap, 0px));
  padding-inline: var(--settings-list-inset);
}

.management-subpage > :is(.settings-card, .settings-editable-list, .security-recovery-list, .settings-detail-list, .store-settings-group, .password-requirements) + .settings-helper,
.management-subpage > :is(.settings-card, .settings-editable-list, .security-recovery-list, .settings-detail-list, .store-settings-group, .password-requirements) + .password-requirements {
  --footnote-parent-gap: 24px;
}

.passkey-settings > :is(.settings-card, .settings-editable-list, .security-recovery-list, .settings-detail-list, .store-settings-group, .password-requirements) + .settings-helper,
.passkey-settings > :is(.settings-card, .settings-editable-list, .security-recovery-list, .settings-detail-list, .store-settings-group, .password-requirements) + .password-requirements {
  --footnote-parent-gap: var(--settings-heading-gap);
}

/* Fields inside an editable card read like every other grouped-list row:
   the label in the row's own 17px label style, the value in the value grey
   on the right, on a 56px row (2026-09-24). The customer form fell short of
   both. Its labels are .field-label-inline, which carries the older form
   style (13px grey) and does not inherit the row's; and its inputs lost to
   ".form input:not([type=checkbox]):not([type=radio]):not([type=file])",
   whose three :not() arguments outrank the customer grid rule, so they kept
   15px dark text in a 44px box and every row stood 60px tall. The employee
   editor and the role-label screen, which are not .form, already read this
   way; these values are theirs. */
/* The same holds in a white card of rows (SettingsEditableCard), which
   the maintenance form uses since 2026-09-28. */
:is(.settings-editable-list, .store-settings-list) .field-label-inline {
  color: inherit;
  font-size: inherit;
  line-height: inherit;
}

.settings-editable-list :is(.settings-editable-row, .postal-inline) > :is(input, select):where(:not(.value-pill, .value-pill-control)) {
  min-height: 40px !important;
  color: var(--settings-value-color) !important;
  font-size: inherit !important;
}

/* ...and without the boxed-input padding, so the value ends on the row's
   right inset like the employee editor's. Selects keep theirs: it holds
   the chevron. */
.settings-editable-list :is(.settings-editable-row, .postal-inline) > input:where(:not(.value-pill, .value-pill-control)) {
  padding: 0 !important;
}

/* At 17px a label and its 任意 marker can outgrow the label column
   (メールアドレス + 任意 is about 146px against 141px), and the flex row
   then broke the label mid-word and stacked 任意 one character per line.
   Let the marker wrap below the label as a unit instead. */
.settings-editable-list .field-label-inline {
  flex-wrap: wrap;
  row-gap: 0;
}

.settings-editable-list .field-label-inline > small {
  white-space: nowrap;
}

/* The same row on a screen that has no screen-specific field rule (the
   security screen's セッションを無効化 picker): the value sits unboxed on
   the right, as the customer and employee editors' own rules already do. */
.settings-editable-list :is(.settings-editable-row, .postal-inline) > :is(input, select):where(:not(.value-pill, .value-pill-control)) {
  width: 100%;
  min-width: 0;
  border: 0 !important;
  border-radius: 0;
  background-color: transparent;
  box-shadow: none;
  text-align: right;
  text-align-last: right;
}

/* Sale form: the 商品 field opens SaleItemPicker. It is the value of a
   settings row, like the rows' own selects: unboxed, grey, on the right. */
.sale-item-field {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 40px;
  border: 0;
  background: transparent;
  padding: 0;
  color: var(--settings-value-color);
  font: inherit;
  text-align: right;
  cursor: pointer;
}

.sale-item-field > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sale-item-field > .is-placeholder {
  color: var(--muted);
}

.sale-item-field > .ti {
  color: var(--muted-light);
  font-size: 18px;
}

/* The item list laid over the sale form. Its top is one purple band, as the
   inventory screen's: the header, then a white search field and the three
   filters (すべて / 貸出していない / 貸出中). */
.sale-item-picker-screen {
  position: fixed;
  z-index: 10060;
  inset: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  overflow: hidden;
  background: var(--bg);
}

.sale-item-picker-top {
  background: var(--accent);
}

.sale-item-picker-controls {
  display: grid;
  gap: 10px;
  padding: 0 max(var(--mobile-page-gutter), env(safe-area-inset-right)) 14px max(var(--mobile-page-gutter), env(safe-area-inset-left));
}

.sale-item-picker-filters {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
}

.sale-item-picker-filter {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 6px;
  height: 32px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  padding: 0 14px;
  color: var(--paper);
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}

.sale-item-picker-filter > span {
  font-weight: 400;
}

/* P4: the day the picker shows availability for, inside its own chip. */
.sale-item-picker-filter > input {
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-weight: 400;
  /* The chip already has its own padding and height; the shared date
     capsule's own padding would widen it and push the filters beside it off
     the screen. The input keeps a 120px floor so the full year stays visible
     (tests/pr126-review-regressions.test.mjs). */
  min-inline-size: 120px;
  height: auto;
  min-height: 0;
  padding: 0;
}

.sale-item-picker-filter[aria-pressed="true"] {
  background: var(--paper);
  color: var(--accent);
}

.sale-item-picker-body {
  overflow-y: auto;
  overscroll-behavior: none;
  padding: var(--page-content-gap) max(var(--mobile-page-gutter), env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom)) max(var(--mobile-page-gutter), env(safe-area-inset-left));
}

.sale-item-picker-list {
  display: grid;
  padding-inline: var(--settings-list-inset);
}

.sale-item-picker-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  min-height: var(--settings-row-height);
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  padding: 8px 0;
  color: var(--ink);
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.sale-item-picker-row:last-of-type {
  border-bottom: 0;
}

.sale-item-picker-row:disabled {
  cursor: default;
}

.sale-item-picker-text {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.sale-item-picker-text > strong {
  font-size: 15px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.sale-item-picker-text > small {
  color: var(--muted);
  font-size: 12px;
}

.sale-item-picker-row > em {
  border-radius: 999px;
  background: var(--chip-bg);
  padding: 3px 8px;
  color: var(--muted);
  font-size: 12px;
  font-style: normal;
  white-space: nowrap;
}

.sale-item-picker-row > .ti {
  color: var(--accent);
  font-size: 20px;
}

.sale-item-picker-row.is-unavailable > .sale-item-picker-text {
  opacity: 0.55;
}

/* 貸出中 reads apart from every other state: the solid accent badge (the
   same weight as 本番), with the name dimmed because it cannot be sold. */
.sale-item-picker-row.is-rented > em {
  background: var(--accent);
  color: var(--paper);
}

.sale-item-picker-row.is-rented > .sale-item-picker-text > strong {
  color: var(--muted);
}

/* A list with more of the screen below it shows five rows and this link to
   the rest (ListPreview), centred as the list card's last row: its own 44px
   target is the room above it, and it reads quieter than the rows' names
   (owner, 2026-09-29: smaller, less space above). */
.list-preview-more {
  position: relative;
  display: flex;
  justify-content: center;
  inline-size: 100%;
  margin: 0;
  font-size: 15px;
}

/* A hairline above すべて見る, as between the rows above it (owner, 2026-10-07). */
.list-preview-more::before {
  position: absolute;
  top: 0;
  right: var(--settings-list-inset);
  left: var(--settings-list-inset);
  block-size: 1px;
  background: var(--list-separator);
  content: "";
}

/* The whole list opened from a page that is not itself a management screen
   (台帳) covers the viewport, above the page's own header and buttons. */
body > .list-preview-screen {
  position: fixed;
  z-index: 10040;
}

/* ItemPhoto: the thumbnail is a button that opens the whole photo. */
.item-photo-button {
  padding: 0;
  cursor: zoom-in;
}

/* The frame holds the tile and the pencil in its top-right corner, which
   registers or changes the photo (owner, 2026-10-09). */
.item-photo-frame {
  position: relative;
  display: grid;
  width: min(100%, 280px);
}

.item-photo-frame .detail-thumb {
  width: 100%;
}

.item-photo-frame > a {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
}

/* The whole photo, as large as the screen allows, on the screen's own
   background (the header and back button are the shared ManagementScreen). */
.item-photo-screen .item-photo-full {
  display: block;
  width: 100%;
  height: auto;
  max-height: calc(100dvh - 160px);
  object-fit: contain;
  border-radius: var(--radius);
}


/* A date's distance from today (今日・明日・あと3日・3日前), in small grey
   type to the date's right on reservation and customer screens. span. keeps
   it above .settings-detail-row span, which styles that row's label. */
span.relative-day {
  margin-inline-start: 6px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 400;
  white-space: nowrap;
}
/* Supervised developer access stays recognizable above every tenant page,
   overlays included: every full-screen layer starts below it, so the role and
   終了 stay reachable while a registration is open. The banner keeps its own
   6px above the text as well as the safe area, which is 0 in a browser. */
body:has(.developer-mode-banner) {
  --developer-banner-height: calc(54px + env(safe-area-inset-top));
}

.developer-mode-banner {
  position: fixed;
  inset: 0 0 auto;
  z-index: 30100;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  min-height: var(--developer-banner-height);
  padding: calc(env(safe-area-inset-top) + 6px) 12px 6px;
  background: var(--accent);
  color: var(--paper);
  font-size: 13px;
}

.developer-mode-exit {
  min-height: 32px;
  padding: 0 12px;
  border: 1px solid var(--paper);
  border-radius: 16px;
  background: transparent;
  color: var(--paper);
}

.developer-mode-error {
  flex-basis: 100%;
  text-align: center;
}

.shell--developer .main:not(:has(.management-screen)) {
  padding-top: calc(var(--developer-banner-height) + 26px);
}

body:has(.developer-mode-banner) :is(.management-screen, .reservation-registration-screen, .operation-registration-screen, .sale-item-picker-screen, .inventory-scan-panel) {
  top: var(--developer-banner-height);
}

/* Below the banner these layers no longer reach the status bar. */
body:has(.developer-mode-banner) :is(.operation-registration-screen, .sale-item-picker-top) {
  padding-top: 0;
}

body:has(.developer-mode-banner) .management-screen-header {
  padding-top: 0;
}

@media (max-width: 767px), (hover: none) and (pointer: coarse) {
  /* Tenant-defined role names may use 20 characters. Keep the banner a
     predictable two-row surface so it never covers a management header. */
  .developer-mode-banner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: 20px 34px;
    justify-content: center;
    gap: 4px 8px;
  }

  body:has(.developer-mode-banner) {
    --developer-banner-height: calc(78px + env(safe-area-inset-top));
  }

  .developer-mode-banner > span:first-child {
    grid-column: 1 / -1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: center;
  }

  .developer-mode-role-select {
    grid-column: 1;
    justify-self: end;
    max-width: calc(100vw - 88px);
    overflow: hidden;
  }

  .developer-mode-exit {
    grid-column: 2;
    grid-row: 2;
  }

  .developer-mode-error {
    grid-column: 1 / -1;
  }

}

/* A screen whose content says what it is keeps its title for screen readers
   only (個人設定: the picture and name come first, 2026-09-28). */
.management-screen-header > h1.management-screen-title-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 信頼済み端末 sits inside the employee editor, whose sections set no gap of
   their own: the revoke card keeps the same 12px from the list above it as
   the Face ID screen's cards do. */
.employee-trusted-mfa-devices .trusted-mfa-actions {
  margin-top: var(--settings-heading-gap);
}

/* PasswordInput: the eye sits inside the field at its right end; the field
   keeps its own look and leaves room for it (2026-09-28). */
.password-input {
  position: relative;
  display: block;
  width: 100%;
}

.password-input > input {
  width: 100%;
  padding-right: 44px;
}

.password-input-toggle {
  position: absolute;
  top: 50%;
  right: 0;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  background: transparent;
  color: var(--muted);
  transform: translateY(-50%);
  -webkit-tap-highlight-color: transparent;
}

.password-input-toggle > i {
  font-size: 20px;
}

/* The code a reset link issued, in the value column of its row: set apart
   by weight and spacing so it reads as a code to type (2026-09-28). */
.reset-personal-code .settings-detail-row > strong {
  color: var(--settings-label-color);
  font-weight: 600;
  letter-spacing: 0.08em;
}

/* スーパー管理者 (signed in): each tenant is its rows and, 12px under them,
   its 開発者として入る row -- the same stack as the Face ID screen. */
.super-admin-tenant {
  display: grid;
  gap: var(--settings-heading-gap);
}

/* A long entry (備考, 処理内容): the label on the row's first line and the
   entry under it across the whole row, inside the same white card, as the
   system's own notes field reads. The box has no border of its own and grows
   with what is typed (AutoGrowTextarea), so nothing is cut off. Short
   entries keep label | value (2026-09-28). */
.store-settings-form .store-settings-list .settings-long-row {
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: 4px;
  height: auto;
  padding: 14px var(--settings-list-inset);
}

.store-settings-form .store-settings-list .settings-long-row > textarea {
  display: block;
  width: 100%;
  min-height: calc(var(--settings-label-size) * 1.45 * 2);
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--ink);
  font-size: var(--settings-label-size);
  line-height: 1.45;
  resize: none;
}

.store-settings-form .store-settings-list .settings-long-row > textarea:focus {
  outline: none;
  box-shadow: none;
}

/* The item editor keeps its own row markup; its 備考 reads the same way. */
.item-editor-panel .item-form > label.item-notes-row > textarea {
  min-height: calc(var(--settings-label-size) * 1.45 * 2);
  padding: 0;
  overflow: hidden;
  font-size: var(--settings-label-size);
  line-height: 1.45;
  resize: none;
}

/* The login form sits under the ログイン方法 switch at the same width: the
   shared .form's side padding (14px on a phone) made the entries and the
   ログイン button 28pt narrower than the switch above them (owner,
   2026-09-29: widths line up on a screen). Top and bottom stay. */
.login-page .form {
  padding-right: 0;
  padding-left: 0;
}

/* ログイン: the entries are one grouped box of rows inside the white login
   card, label | entry with a hairline between rows, instead of a caption
   over each boxed field (2026-09-28). */
.login-page .form .login-field-group {
  display: grid;
  border: var(--settings-divider-width) solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.login-page .form .login-field-group > .login-field-row {
  position: relative;
  display: grid;
  grid-template-columns: fit-content(50%) minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  min-height: var(--settings-row-height);
  padding: 0 16px;
  color: var(--settings-label-color);
  font-size: 16px;
  line-height: 1.3;
}

.login-page .form .login-field-group > .login-field-row:not(:last-child)::after {
  position: absolute;
  right: 16px;
  bottom: 0;
  left: 16px;
  height: var(--settings-divider-width);
  background: var(--settings-divider-color);
  content: "";
}

.login-page .form .login-field-group > .login-field-row > span:first-child {
  white-space: nowrap;
}

.login-page .form .login-field-group > .login-field-row input:not([type="hidden"]) {
  min-width: 0;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--settings-label-color);
  font-size: 16px;
  text-align: right;
}

.login-page .form .login-field-group > .login-field-row .password-input > input {
  padding-right: 44px;
}

/* The heading under the tabs stays on one line on every phone: at the
   browser's own 24px, 「メールアドレスでログイン」 broke before its last
   two characters at 390px and below (2026-09-28). */
.login-form-groups h2 {
  font-size: 20px;
}

/* CSVインポート: the file row opens the system picker; the input itself is
   kept in the row, out of sight, so tapping anywhere on the row reaches it
   (2026-09-28). A long file name is cut with an ellipsis. */
.csv-file-row {
  position: relative;
  cursor: pointer;
}

.csv-file-row > strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.csv-file-row > .csv-file-input {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  opacity: 0;
  pointer-events: none;
}

/* ホーム (2026-09-28): each section is the shared grey heading over a
   SettingsCard; 今日 and 今週 share one card behind the app's segmented
   pills (商品のタグ管理's); the counts are 店舗の状況's own cells in one row;
   the rows are divided by hairlines inside the card's inset and each keeps
   to one line; 台帳's すべて見る is the card's last row. */
.home-dashboard .home-section {
  display: grid;
  min-width: 0;
}

.home-dashboard .home-section-card {
  /* The shared schedule sizing, re-measured for these rows: three rows
     show at once, the rest scroll inside the card. */
  --home-schedule-section-heading-height: auto;
  --home-schedule-compact-row-height: var(--list-row-height);
  --home-schedule-row-gap: 0px;
  --home-schedule-list-inset-block: 0px;
  --home-schedule-list-height: calc(var(--home-schedule-compact-row-height) * var(--home-schedule-visible-rows));
  display: grid;
  min-width: 0;
  padding-top: var(--settings-list-inset);
}

/* Equal-width pills in one row (ホーム's 今日/今週, 台帳's 予約一覧/カレンダー).
   Both choices sit in one rounded track, so the unchosen one is not bare text
   (owner, 2026-10-07): white on the page, the page's grey inside a white card. */
.segmented-pills--even {
  display: grid;
  grid-auto-columns: minmax(0, 1fr);
  grid-auto-flow: column;
  gap: 4px;
  padding: 4px;
  border-radius: 999px;
  background: var(--paper);
}

.settings-card .segmented-pills--even {
  background: var(--bg);
}

.home-period-switch {
  margin-inline: var(--settings-list-inset);
}

/* 予約・貸出・返却 above the rows: one line each, label beside number. */
.home-dashboard .home-count-summary {
  margin-block: var(--settings-selection-control-gap);
  padding-block: 0;
}

/* Segmented pills (2026-09-28): the selected pill is one shape that slides
   from the old choice to the new one, as iOS's segmented control does. The
   buttons keep their own accent until the pill has been measured. */
.segmented-pills {
  position: relative;
  isolation: isolate;
}

.segmented-pills-indicator {
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
  border-radius: 999px;
  background: var(--accent);
  pointer-events: none;
}

.segmented-pills-indicator.is-animated {
  transition: transform 280ms cubic-bezier(0.2, 0.8, 0.2, 1), width 280ms cubic-bezier(0.2, 0.8, 0.2, 1), height 280ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  .segmented-pills-indicator.is-animated {
    transition: none;
  }
}

/* 一覧の行 (ListRow, 2026-09-28): a compact line as the old Home rows were
   -- the time, then 氏名 / 種別 taking what the name needs, 用途 in grey in
   the rest, the badge, a chevron -- with hairlines between the rows. */
.list-rows {
  display: grid;
  padding: 0 var(--settings-list-inset);
}

.list-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  height: var(--list-row-height);
  color: var(--settings-label-color);
  font-size: 12px;
  line-height: 16px;
  white-space: nowrap;
}

.list-row:not(:last-child)::after {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: var(--settings-divider-width);
  background: var(--settings-divider-color);
  content: "";
}

.list-row.is-muted {
  opacity: 0.58;
}

.list-row-lead {
  flex: 0 0 auto;
  padding-right: 8px;
  border-right: var(--settings-divider-width) solid var(--settings-divider-color);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.list-row-text {
  display: flex;
  flex: 1 1 auto;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  overflow: hidden;
}

.list-row-text > strong {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  font-weight: 500;
  text-overflow: ellipsis;
}

.list-row-detail {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  color: var(--settings-value-color);
  text-overflow: ellipsis;
}

.list-row > .schedule-warning-badge {
  flex: 0 0 auto;
  padding: 2px 8px;
}

.list-row-chevron {
  flex: 0 0 auto;
  color: var(--list-chevron);
  font-size: 14px;
}

/* 件数の枠 (SummaryCells, 2026-09-28): counts three to a row, label over
   number, hairlines between, and the card's one inset on every side. */
.summary-cells {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  padding: var(--settings-list-inset);
}

.summary-cell {
  display: grid;
  place-items: center;
  align-content: center;
  padding: 0 6px 10px;
  border-right: var(--settings-divider-width) solid var(--settings-divider-color);
  color: var(--ink);
  text-align: center;
}

/* A single row of counts in a stack of cards: the small card padding above and
   below, with no extra space under the cells. */
.summary-cells--compact {
  padding-block: var(--card-padding-small);
}

.summary-cells--compact > .summary-cell {
  padding-block: 0;
}

.summary-cell:nth-child(3n) {
  border-right: 0;
}

.summary-cell:nth-child(n + 4) {
  padding-top: 10px;
  padding-bottom: 0;
  border-top: var(--settings-divider-width) solid var(--settings-divider-color);
}

.summary-cell > span {
  font-size: 12px;
  font-weight: 500;
  line-height: 14px;
}

.summary-cell > strong {
  font-size: 24px;
  font-weight: 700;
  line-height: 30px;
}

.summary-cell.is-danger {
  color: var(--danger);
}

.summary-amount-card {
  display: grid;
  gap: 6px;
  color: var(--ink);
}

.summary-amount-card > span {
  font-size: var(--ui-row-label-size);
}

.summary-amount-card > strong {
  color: var(--accent);
  font-size: 32px;
  line-height: 1.2;
}

/* A single row of counts reads as one line: label beside number. */
.summary-cells.home-count-summary > .summary-cell {
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: 8px;
  padding-block: 0;
}

.summary-cells.home-count-summary > .summary-cell > strong {
  font-size: 20px;
  line-height: 28px;
}

/* 着付け未設定: a SettingsCard row under the clock, the text and a chevron
   to the list (no decorative icon). */
.home-dresser-alert {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  min-height: var(--settings-row-height);
  padding: 0 var(--settings-list-inset);
  color: var(--settings-label-color);
}

.home-dresser-alert > strong {
  overflow: hidden;
  font-size: var(--settings-label-size);
  font-weight: 400;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.home-dresser-alert > i {
  color: var(--list-chevron);
  font-size: 18px;
}

/* 対応が必要な予約: the same row with two text lines, on the shared red card. */
.home-dresser-alert > span {
  display: grid;
  min-width: 0;
  padding-block: var(--settings-row-padding-block);
}

.home-dresser-alert > span > strong {
  font-size: var(--settings-label-size);
  font-weight: 600;
}

.home-dresser-alert > span > small {
  font-size: 14px;
}

.settings-card--warning {
  background: var(--warning-bg);
}

.settings-card--warning.home-dresser-alert > span > strong,
.settings-card--warning.home-dresser-alert > span > small {
  color: var(--danger);
}

/* P7 準備リスト: the day between 前の日 and 次の日, then one block per
   reservation with a tick per item; the same card is the printed paper. */
.prep-date-nav {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  min-height: var(--settings-row-height);
  text-align: center;
}

.prep-date-nav > a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}

.prep-checklist {
  display: grid;
  gap: var(--settings-section-gap);
  padding: var(--settings-list-inset);
}

.prep-checklist h2 {
  margin: 0;
  font-size: var(--ui-page-title-size);
}

.prep-reservation h3 {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  font-size: var(--settings-label-size);
}

.prep-reservation > p {
  margin: 4px 0 8px;
  color: var(--list-secondary-label);
  font-size: var(--settings-footnote-size);
}

.prep-reservation ul {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.prep-reservation label {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 10px;
}

.prep-reservation input[type="checkbox"] {
  width: 22px;
  height: 22px;
  margin: 1px 0 0;
  accent-color: var(--accent);
}

.prep-reservation small {
  display: block;
  color: var(--list-secondary-label);
}

/* Wide touch screens (iPad, 2026-09-28): the phone layout at any width,
   laid out for the room. Content keeps a readable column in the middle,
   the tab bar keeps a phone-like width, and the home screen puts 直近の予定
   and 店舗の状況 side by side once the screen is wide enough. A mouse-driven
   screen keeps the separate desktop layout. */
@media (min-width: 768px) and (hover: none) and (pointer: coarse) {
  .main > .page-transition,
  .management-screen-content {
    width: 100%;
    max-width: 760px;
    margin-inline: auto;
  }

  .sidebar .nav {
    max-width: 600px;
    margin-inline: auto;
  }
}

@media (min-width: 768px) and (orientation: landscape) and (hover: none) and (pointer: coarse) {
  .main > .page-transition:has(> .home-dashboard),
  .main > .page-transition:has(.home-dashboard) {
    max-width: 1120px;
  }

  .home-dashboard {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    column-gap: 24px;
    align-items: start;
  }

  .home-dashboard > :not(.home-section) {
    grid-column: 1 / -1;
  }

  .home-dashboard > .home-section:first-of-type {
    grid-column: 1;
    grid-row: span 2;
  }
}

/* ホーム on a phone or tablet (2026-09-28): the dashboard keeps its fixed
   frame but scrolls inside it when its sections are taller than the screen,
   so the 棚卸し and メンテナンス buttons can always be reached. An earlier
   rule set its overflow back to visible, which let them sit under the tab
   bar. The frame already ends above the tab bar, so the room under the last
   row is only the cards' inset: with the tab bar's height added as well, an
   iPhone 16 Pro Max could drag 89px of empty space into view. */
@media (max-width: 767.98px), (hover: none) and (pointer: coarse) {
  .home-dashboard {
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: none;
    padding-bottom: var(--settings-list-inset);
  }
}

/* A phone short enough for ホーム to scroll (iPhone SE) brings the buttons
   down to the frame's end, where the QR button rises 20px above the tab
   bar: the room under them clears it as well. */
@media (max-width: 767.98px) and (max-height: 880px), (hover: none) and (pointer: coarse) and (max-height: 880px) {
  .home-dashboard {
    padding-bottom: calc(var(--settings-list-inset) + 20px);
  }
}

/* P1: お見積書 / ご予約確認書 -- a paper on the shared card. Its rows are the
   shared detail rows; the title, the addressee, the photos and the store's
   name under them are the paper's own. */
.reservation-document {
  display: grid;
  gap: var(--settings-section-gap);
  padding-block: var(--settings-list-inset);
}

/* Everything starts where the shared rows' text starts (docs/ui-rules.md rule 6). */
.reservation-document > :not(.settings-detail-list) {
  padding-inline: var(--settings-list-inset);
}

.reservation-document > header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--settings-list-inset);
}

.reservation-document > header > h2 {
  margin: 0;
  font-size: var(--ui-section-title-size);
}

.reservation-document > header > p,
.reservation-document > footer {
  margin: 0;
  color: var(--settings-value-color);
  font-size: var(--settings-value-size);
  text-align: right;
}

.reservation-document > p {
  margin: 0;
}

.reservation-document > .reservation-document-to {
  font-weight: 600;
}

.reservation-document-photos {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--settings-list-inset);
}

.reservation-document-photos > img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.reservation-document > footer {
  display: grid;
}

/* One paper layout for estimates and confirmations; ReceiptDocument keeps
   its existing detail rows. The outer surface remains the shared card. */
.reservation-document .document-paper {
  color: var(--ink);
  font-size: 14px;
}

.reservation-document .document-paper-heading h2 {
  margin: 0;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--accent);
  text-align: center;
  font-size: 24px;
  letter-spacing: 0.18em;
}

.reservation-document .document-paper-issue {
  display: grid;
  justify-items: end;
  margin: 12px 0 22px;
  font-size: 12px;
}

.reservation-document .document-paper-recipient {
  margin: 0 0 6px;
  font-size: 18px;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 4px;
}

.reservation-document .document-paper-lead {
  margin: 0 0 18px;
}

.reservation-document .document-paper-amount {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 12px;
  margin-bottom: 18px;
  background: var(--paper-soft);
}

.reservation-document .document-paper-amount strong {
  font-size: 21px;
  white-space: nowrap;
}

.reservation-document .document-paper-schedule {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 0 0 18px;
  padding: 10px 0;
  border-block: 1px solid var(--line);
}

.reservation-document .document-paper-schedule dt {
  color: var(--muted);
  font-size: 12px;
}

.reservation-document .document-paper-schedule dd {
  margin: 3px 0 0;
  font-size: 11px;
  white-space: nowrap;
}

.reservation-document .document-paper-items {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 12px;
}

.reservation-document .document-paper-items col:first-child {
  width: 45%;
}

.reservation-document .document-paper-items col:nth-child(2) {
  width: 20%;
}

.reservation-document .document-paper-items col:nth-child(3) {
  width: 12%;
}

.reservation-document .document-paper-items col:last-child {
  width: 23%;
}

.reservation-document .document-paper-items thead {
  background: var(--paper-soft);
}

.reservation-document .document-paper-items th,
.reservation-document .document-paper-items td {
  padding: 7px 3px;
  border-bottom: 1px solid var(--line);
  overflow-wrap: anywhere;
}

.reservation-document .document-paper-items th:first-child,
.reservation-document .document-paper-items td:first-child {
  text-align: left;
}

.reservation-document .document-paper-items th:not(:first-child),
.reservation-document .document-paper-items td:not(:first-child) {
  text-align: right;
}

.reservation-document .document-paper-items th:nth-child(3),
.reservation-document .document-paper-items td:nth-child(3) {
  text-align: center;
}

.reservation-document .document-paper-items tr {
  break-inside: avoid;
}

.reservation-document .document-paper-ending {
  display: grid;
  justify-content: end;
  margin-top: 16px;
}

.reservation-document .document-paper-summary,
.reservation-document .document-paper-issuer {
  width: min(100%, 255px);
  border-top: 1px solid var(--line);
}

.reservation-document .document-paper-summary {
  margin: 0 0 18px;
  padding-top: 5px;
}

.reservation-document .document-paper-summary > div {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
}

.reservation-document .document-paper-summary dt,
.reservation-document .document-paper-summary dd {
  margin: 0;
}

.reservation-document .document-paper-summary-total {
  margin-top: 5px;
  border-top: 1px solid var(--line);
  font-weight: 700;
}

.reservation-document .document-paper-issuer {
  display: grid;
  padding-top: 10px;
  overflow-wrap: anywhere;
}

.reservation-document .document-paper-issuer strong {
  margin-bottom: 3px;
}

@media print {
  .reservation-document .document-paper {
    font-size: 10pt;
  }

  .reservation-document .document-paper-items thead {
    display: table-header-group;
  }

  .reservation-document .document-paper-ending {
    break-inside: avoid;
  }

  .reservation-document .document-paper .reservation-document-photos {
    display: none;
  }
}

/* ホーム's empty 今日/今週: the message sits in the middle of the rows' room,
   not at its top (owner, 2026-10-07). */
.home-schedule-scroll > .schedule-empty-state {
  display: grid;
  block-size: 100%;
  min-block-size: 100%;
  place-items: center;
  margin: 0;
}

/* A permission is a card with its sentence under it; the next card follows
   closely because the two say nearly the same thing (owner, 2026-10-08). */
.employee-permission-group {
  display: grid;
  gap: 0;
}

.employee-permission-group > .settings-helper + .settings-editable-list {
  margin-top: var(--settings-heading-gap);
}

.employee-permission-group > .employee-permission-note {
  margin-top: var(--settings-heading-gap);
}

/* Under a permission's card the sentence reads like any footnote, and the
   account actions start a section gap below whatever precedes them. */
.employee-permission-group > .settings-helper {
  padding-inline: var(--settings-list-inset);
  color: var(--list-secondary-label);
  font-size: var(--settings-footnote-size);
  line-height: var(--settings-footnote-line-height);
  text-wrap: wrap;
}

.employee-account-actions {
  margin-top: var(--settings-section-gap);
}
