/*
 * Stage 4A — mobile responsive layer.
 *
 * Loaded LAST in <head> (after each page's own stylesheets) so its mobile
 * overrides win the cascade. Everything that could affect the desktop layout is
 * kept inside width-bounded @media queries; only a couple of universally safe
 * rules live at the top level. This file never changes colours, routes, field
 * names or form structure — it only reflows the existing markup for small
 * screens.
 */

/* ---- Universally safe (all viewports) ------------------------------------ */

/* Stop iOS/Safari from auto-inflating text after an orientation change. */
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Media never forces horizontal overflow. */
img,
svg,
video,
canvas {
  max-width: 100%;
}

/* ---- Phones / small tablets --------------------------------------------- */
@media (max-width: 768px) {
  html,
  body {
    max-width: 100%;
    overflow-x: hidden;
  }

  /* UI FOUNDATION v1 — `clip`, not `hidden`, on <body>.

     `overflow-x: hidden` makes an element a SCROLL CONTAINER on the other
     axis. <body> therefore became the nearest scrolling ancestor of every
     sticky element on the page — and <body> itself never scrolls, the
     document does — so `position: sticky` inside it silently did nothing on a
     phone. That is what kept the global 「戻る」 bar from following the scroll
     at 390 while it worked at 1280.

     `overflow-x: clip` cuts off horizontal overflow exactly as `hidden` did
     but creates NO scroll container, so sticky works again. The `hidden`
     declaration above is left in place deliberately: a browser too old to
     understand `clip` ignores this line and keeps the old, still-correct
     horizontal guard. <html> keeps `hidden` — it is the document scroller
     already, so nothing about it changes. */
  body {
    overflow-x: clip;
  }

  /* Honour iPhone notch / rounded-corner safe areas. */
  body {
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
  }

  /* UI FOUNDATION v1 — the phone's sticky offset is ZERO.

     The desktop backbar hangs below a sticky header, so it offsets itself by
     --revf-header-height. On a phone the header below is deliberately NOT
     sticky (next rule), so there is nothing above the backbar to clear: it
     sticks to the top of the viewport itself. Leaving the desktop offset in
     place here would park 「戻る」 120px down the screen, on top of the
     content, which is exactly what §12 says it must not do. */
  :root {
    --revf-header-height: 0px;
  }

  /* --- Header: stack, shrink the logo, and DON'T stay sticky (a tall sticky
         header would cover the screen on a phone). --- */
  .site-header {
    position: static;
    height: auto;
    /* MOBILE-HEADER-SAFE-AREA v1 — the top inset, and a little clear air on
       top of it.

       This rule used to read `padding: 8px 0 calc(8px + safe-area-inset-
       BOTTOM)`: it spent the bottom inset on a bar that sits at the TOP of
       the document (an inset this element can never be affected by) and left
       the top at a flat 8px. On a home-screen install that put メニュー /
       通知 / ログアウト about 29px from the top of the window — inside the
       47-59px the status bar and the Dynamic Island occupy — so the taps
       either hit the system UI or landed on the very edge of the control.

       calc(), not max(): max(10px, inset) would stop the controls exactly at
       the lower edge of the island with nothing between, which clears the
       island but still reads as crammed against it. Adding the 10px keeps
       the same clear air above the row whether or not the device has an
       inset, and the plain 10px declaration above it is what a browser
       without env() falls back to. */
    padding-top: 10px;
    padding-top: calc(10px + var(--revf-safe-top));
    padding-bottom: 8px;
  }

  /* Stage UI-1: a wrapping row, not a column. The logo and the メニュー button
     share the first line and the header icons follow, which costs two rows
     instead of three and keeps the fold closer to the page content. */
  .header-inner {
    width: calc(100% - 24px);
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    row-gap: 8px;
    column-gap: 12px;
    /* The desktop bar is 92px tall for a nav that is not even shown here — a
       phone header only has to clear its 48px controls. */
    min-height: 48px;
  }

  /* The stacked mark on a phone: wide enough that 不動産 Value Finder under
     the house is still readable, narrow enough to share the row with the
     メニュー button and the two controls. Width only — a height cap would
     shrink the wordmark faster than the mark. */
  .brand-logo-link {
    width: auto;
    height: auto;
    flex: 0 0 auto;
  }

  .brand-logo-image {
    width: 112px;
    height: auto;
  }

  /* The primary nav is a full-width, tappable column on a phone.
     Stage UI-1: this used to be `display: flex !important`, which was needed
     because the old base sheet hid .main-nav outright below 720px. The shared
     layer no longer hides it, and the !important actively broke the new
     メニュー disclosure — it out-ranked the collapse rule, so the menu could
     never close. Plain `display: flex` keeps this open by default (and with
     JavaScript off it stays open, so nothing is unreachable) while letting
     revf-ui.css collapse it behind the button when scripting is available. */
  .main-nav {
    display: flex;
    justify-self: stretch;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 2px;
    height: auto;
  }

  .main-nav a {
    height: auto;
    min-height: 48px;
    font-size: 16px;
  }

  .main-nav a.active::after {
    display: none;
  }

  /* --- Content width & padding --- */
  .main-content {
    width: 100%;
    padding-left: 12px;
    padding-right: 12px;
    padding-top: 18px;
    padding-bottom: 28px;
  }

  .dashboard-container,
  .container {
    width: 100% !important;
    max-width: 100%;
    padding-left: 12px;
    padding-right: 12px;
  }

  /* REVF-GLOBAL-BACK v1: the 「← 戻る」 bar sits above .main-content, whose
     own top padding already separates it from the page title, so it only
     needs a little air under the header on a phone. Its inner element carries
     .dashboard-container, so the gutter above lines it up with the content
     column at every width and no extra rule is needed for that. */
  .revf-backbar {
    padding-top: 14px;
    /* REVF-CHROME-SMOKE v1 — stick BELOW the status bar, not underneath it.

       This rule used to leave the sticky offset at 0, which is what
       --revf-header-height is on a phone (the header above is static and
       scrolls away, so there is nothing to clear). On an ordinary mobile
       browser that is still right: the browser's own chrome owns the notch
       and env(safe-area-inset-top) is 0.

       On a HOME-SCREEN INSTALL it was wrong, and measurably so. pwa_head.html
       ships viewport-fit=cover and black-translucent, so the document starts
       at y=0 - underneath the status bar and the Dynamic Island - and a bar
       pinned to 0 is pinned INSIDE that band. The whole 44px tap target sat
       within the 47-59px an iPhone reports there: drawn under the system UI,
       and not tappable. It is the one control this product promises on every
       screen, and on the device the promise mattered most it was the one
       control that was not there.

       --revf-safe-top is the same token .site-header already offsets itself
       by (revf-ui.css §1), so both pieces of chrome read ONE value and cannot
       drift. It is 0px everywhere without an inset, which is every desktop
       browser, every headless run and mobile Safari itself - so this changes
       nothing at all outside a home-screen install.

       Declared twice for the same reason the token is: the literal always
       parses, and a browser too old for the var() keeps a working offset
       instead of an invalid declaration.

       test_chrome_layout_smoke.py measures this with the inset substituted,
       in Chromium and in WebKit, because neither engine reports a real one. */
    top: 0px;
    top: var(--revf-safe-top);
  }

  /* Cards keep breathing room but never overflow. */
  .card,
  .panel {
    max-width: 100%;
    margin-left: 0;
    margin-right: 0;
  }

  /* --- Long content wrapping (URLs, property titles, memos) --- */
  .brand-logo-link + *,
  .page-title,
  .page-title-row,
  h1,
  h2,
  h3,
  p,
  li,
  a.wrap,
  .property-title,
  .break-anywhere {
    overflow-wrap: anywhere;
    word-break: break-word;
  }

  /* --- Wide tables: horizontal scroll instead of crushing every column.
         display:block turns the table into a scroll container while the rows /
         cells keep their intrinsic table layout, so headings and amounts stay
         legible. --- */
  table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  table thead th {
    white-space: nowrap;
  }

  /* Explicit scroll wrappers (if a template already provides one). */
  .table-wrap,
  .table-scroll,
  .table-responsive {
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* --- Forms: full-width, comfortable, no iOS zoom (>=16px), stacked rows. --- */
  input,
  select,
  textarea {
    max-width: 100%;
    width: 100%;
    box-sizing: border-box;
    font-size: 16px;
  }

  /* Keep inline checkboxes / radios their natural size. */
  input[type="checkbox"],
  input[type="radio"] {
    width: auto;
    min-height: 0;
  }

  textarea {
    overflow-x: hidden;
  }

  .form-row,
  .field-row {
    flex-direction: column;
    align-items: stretch;
  }

  label {
    display: block;
  }

  /* Tap targets: buttons and button-like links get a comfortable height and
     wrap instead of overflowing when several sit in a row. */
  button,
  .button,
  .btn,
  input[type="submit"],
  input[type="button"],
  a.button,
  a.btn {
    min-height: 44px;
  }

  /* GLOBAL UI SHELL FINAL v1: the compact button reaches the 44px floor too.

     The 44px rule above is an ELEMENT selector, so `.revf-button--sm` (a
     class) beat it on specificity and 絞り込み / リセット / 希望条件を保存
     stayed at their desktop height on a phone — measured 34px at 390x844,
     ten pixels under the floor every other control on the screen keeps. Named
     explicitly rather than by raising the generic rule's specificity, so the
     one modifier that was escaping it is the one thing that changes. */
  .revf-button--sm {
    min-height: 44px;
  }

  /* The directory 絞り込み pills (仲介業者 / 金融機関) are links a member taps to
     filter the list, not badges — 38px is a chip's height, not a target's. The
     COUNT inside them (.dir-pill-count) stays exactly as it is: it is a number,
     and nothing about it is tappable on its own. */
  .dir-pill {
    min-height: 44px;
  }

  .nav-buttons,
  .card-action-row,
  .button-row,
  .actions,
  .form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
  }

  /* Sticky helpers inside pages should not blanket the small screen. */
  .sticky,
  .is-sticky {
    position: static;
  }
}

/* The phone header gains a little of the same breathing room, but only a
   little: it is already 99px tall with the stacked mark. */
@media (max-width: 768px) {
  .header-inner {
    padding-top: 12px;
    padding-bottom: 8px;
  }

  /* Two by two, so the label and the number never share a cramped column. */
  .dashboard-kpi-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--revf-space-3);
  }

  /* GLOBAL UI SHELL FINAL v1: and the desktop 2 + 3 spans come off with it.

     revf-ui.css lays the five cards on a SIX-column track and gives each child
     an explicit span — 3 for the first two, 2 for the rest. Re-declaring
     grid-template-columns here is not enough to undo that: a span SURVIVES a
     change of track, and a `span 3` item on a two-column grid forces implicit
     columns rather than wrapping into it.

     BOTH desktop selectors are named, not just `> *`. Loading last does not
     help against a HIGHER-specificity rule, and
     `.dashboard-kpi-grid > :nth-child(-n + 2)` is (0,2,0) against `> *`'s
     (0,1,0) — so a lone `> *` reset lost, and measured at 390x844 the two
     取得 cards kept `span 3` while 抽出した潜在価値物件 / 金融機関融資候補物件 /
     詳細分析物件 were crushed into a 0px + 159px + 159px implicit track, 709px
     tall and overlapping each other: the middle card could not be tapped at
     all. In a selector list each selector keeps its own specificity, so the
     second one here ties with the desktop rule and wins on order. */
  .dashboard-kpi-grid > *,
  .dashboard-kpi-grid > :nth-child(-n + 2) {
    grid-column: auto;
  }

  /* ACQUIRED PROPERTY WORKSPACE v1: on a phone the five cards STACK. At 390px
     a two-column card is ~170px wide, which is not enough for
     「金融機関融資候補物件」 or 「抽出した潜在価値物件」 to stay on one line —
     they wrapped mid-word. One column per row gives every label its width back
     and makes the five main routes a list you thumb through. */
  @media (max-width: 560px) {
    .dashboard-kpi-grid {
      grid-template-columns: minmax(0, 1fr);
    }

    .metric-card {
      min-height: 0;
      padding: var(--revf-space-4);
    }
  }
}

/* ---- Very small phones --------------------------------------------------- */
@media (max-width: 480px) {
  .main-nav {
    gap: 2px;
  }

  /* 16px, not 15px: the nav is the one place a phone user reads at arm's
     length, and it shares the row budget with nothing else. */
  .main-nav a {
    font-size: 16px;
  }

  .brand-logo-image {
    width: 104px;
  }
}

/* ---- Stage 4B: logout control in the shared header ----------------------- */
.header-icons {
  display: flex;
  align-items: center;
  gap: var(--revf-space-3);
}

/* The phone/compact header keeps the full-size controls. The desktop
   step-down at 1200 is scoped to >=1181 so it never reaches here, and every
   target stays at or above 48px. 1180 matches the width where revf-ui.css
   hands the nav over to the メニュー button. */
@media (max-width: 1180px) {
  .icon-button {
    width: 48px;
    height: 48px;
  }

  .icon-button svg {
    width: 28px;
    height: 28px;
  }

  .nav-toggle {
    min-height: 48px;
    min-width: 48px;
  }

  .nav-toggle svg {
    width: 28px;
    height: 28px;
  }

  /* MOBILE-HEADER-SAFE-AREA v1 — the HIT area, not just the drawn one.

     通知 is a 48px CIRCLE and メニュー / ログアウト are 48px rounded
     rectangles, so border-radius clips their own corners out of the pointer
     target. Measured with elementFromPoint: the four corners of a 44x44
     square centred on 通知 fall outside the circle (a 48px circle only
     contains a 34px square) and hit the bar behind it, so a thumb aimed at
     the edge of the glyph misses the control entirely.

     The drawn shape is untouched; this transparent overlay restores the full
     rectangle behind it. width/height are the control's own box and the
     min-* pair is the 44px floor, so the target can never grow PAST the
     control into its neighbour — it only reclaims the corners the radius was
     cutting off. */
  .nav-toggle,
  .icon-button,
  .logout-button {
    position: relative;
  }

  .nav-toggle::after,
  .icon-button::after,
  .logout-button::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100%;
    height: 100%;
    min-width: 44px;
    min-height: 44px;
  }
}

.logout-form {
  margin: 0;
}

.logout-button {
  /* This sheet loads last, so the value here is the one that applies at every
     width — it has to match the other right-hand controls, not undercut them. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 50px;
  padding: 8px 18px;
  font-size: 15px;
  font-weight: 600;
  color: #0f9f9a;
  background: #ffffff;
  border: 1px solid #0f9f9a;
  border-radius: 8px;
  cursor: pointer;
}

/* 6th review pass: the logout label is clipped at EVERY width, not just below
   1200. The bar has three things competing for it — a wordmark that grew
   again, four tab-shaped nav entries, and the right-hand controls — and the
   word ログアウト was the only one of the three whose text was not carrying
   information the glyph could not. Clipped, not removed: the accessible name
   is still 「ログアウト」, and the control is now the same 54px circle-sized
   button as the notification bell beside it.

   The ~79px this frees is what lets the nav sit right of centre without the
   tabs having to shrink. */
/* REVF-OWNER-ADMIN v1: the two doors between the member app and the OWNER
   ADMIN clip their words at EVERY width, for exactly the reason ログアウト does
   above — the glyph plus the accessible name says it, and the ~200px the two of
   them would otherwise cost is what pushes the last navigation tab under the
   icons at 1280. */
.admin-user-view .control-label,
.admin-entry-link .control-label,
.logout-button .control-label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.logout-button {
  gap: 0;
  min-width: 50px;
  padding: 0;
}

@media (max-width: 1200px) {
  /* 48px, matching the icon buttons at this step — this sheet loads last, so
     without it the unscoped value above would leave the logout control taller
     than everything beside it. */
  .logout-button {
    min-width: 48px;
    min-height: 48px;
  }
}

/* 4th review pass — the phone header is ONE row: wordmark + メニュー + 通知 +
   ログアウト, every control 48px.

   It used to wrap onto two rows (137px tall) because both buttons carried a
   text label and the decorative initials took a fourth slot. Below 640px the
   labels are clipped rather than removed, so a screen reader still announces
   「メニュー」/「ログアウト」, and the glyph alone carries the meaning
   visually. */
@media (max-width: 640px) {
  /* Tighter gutters and gaps: every pixel saved here is a pixel the wordmark
     keeps, and the wordmark is the only element that has to give way. */
  .header-inner {
    width: calc(100% - 16px);
    /* MOBILE-HEADER-SAFE-AREA v1: 10px, not 5px. Three 48px controls 5px
       apart are one mis-aimed thumb away from each other; measured at 390px
       the row only needs 278px of the 374 available, so the separation costs
       the wordmark nothing. */
    column-gap: 10px;
    /* A little of the same breathing room as the desktop bar, but only a
       little: the stacked mark already makes this header ~100px tall. */
    padding-top: 8px;
    padding-bottom: 5px;
  }

  .brand-logo-link {
    padding: 4px 0;
  }

  .nav-toggle .control-label,
  .logout-button .control-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .nav-toggle,
  .logout-button {
    gap: 0;
    min-width: 48px;
    min-height: 48px;
    padding: 0;
  }

  .logout-button svg {
    width: 24px;
    height: 24px;
  }

  .header-icons {
    /* Matches the row gap above, so 通知 and ログアウト are as far apart from
       each other as メニュー is from them. */
    gap: 10px;
  }

  /* Decorative initials: the row is worth more than the avatar, and it is
     already aria-hidden, so nothing is lost by dropping it here. */
  .icon-button.avatar {
    display: none;
  }

  /* 160px = three 48px controls plus their gaps. The stacked mark is only
     104-112px wide, so it clears that comfortably at 375 and never starts a
     wrap; the cap is here as a floor-guard for very small phones. */
  .brand-logo-link {
    flex: 0 1 auto;
    min-width: 0;
    height: auto;
    max-width: calc(100% - 160px);
  }

  .brand-logo-image {
    height: auto;
    min-width: 0;
    max-width: 100%;
  }
}

.logout-button:hover {
  background: #0f9f9a;
  color: #ffffff;
}

/* ---- Stage WEB-4: stacked tables on phones -------------------------------
 *
 * The rule above turns a wide table into its own horizontal scroller, which
 * keeps every column legible but still leaves a 641px-wide grid inside a 390px
 * screen (and, with html/body overflow-x hidden, a document that overflows even
 * though the overflow is clipped). For the intake queues that is the wrong
 * trade: they are records to read, not a grid to compare across.
 *
 * A table that opts in with .revf-stack-table becomes one card per row below
 * 640px. Every cell keeps its value and gains its column's heading, taken from
 * the data-label the template writes next to the same text the <th> carries, so
 * nothing is dropped, nothing is hidden and no JavaScript is involved — the
 * markup is the same table at every width, and above 640px it renders exactly
 * as it always has.
 *
 * A cell with data-label="" (the row's action link) prints no heading, because
 * its column has none.
 */
@media (max-width: 640px) {
  /* The wrapper is only a scroll container for a real table; a stacked one
     needs no scrolling and no second frame around cards that have their own. */
  .revf-table-wrap--stack {
    overflow-x: visible;
    border: 0;
    background: none;
    box-shadow: none;
    border-radius: 0;
  }

  .revf-stack-table {
    display: block;
    width: 100%;
    max-width: 100%;
    overflow-x: visible;
    border: 0;
    background: none;
    box-shadow: none;
    font-size: var(--revf-font-size-sm, 13px);
  }

  /* The header row still names every column for assistive technology; each
     cell repeats the name visually via data-label. */
  .revf-stack-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .revf-stack-table tbody,
  .revf-stack-table tr,
  .revf-stack-table td {
    display: block;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
  }

  .revf-stack-table tr {
    margin-bottom: var(--revf-space-3, 12px);
    padding: 4px 0;
    border: 1px solid var(--revf-border, #dbe3ea);
    border-radius: var(--revf-radius-lg, 12px);
    background: var(--revf-surface, #ffffff);
    box-shadow: var(--revf-shadow-xs, 0 1px 2px rgba(16, 24, 40, 0.05));
  }

  .revf-stack-table tr:last-child {
    margin-bottom: 0;
  }

  .revf-stack-table td {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 4px 12px;
    padding: 8px 12px;
    text-align: left;
    border: 0;
    border-bottom: 1px solid var(--revf-border-faint, #eef2f6);
    overflow-wrap: anywhere;
  }

  .revf-stack-table tr td:last-child {
    border-bottom: 0;
  }

  .revf-stack-table td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: var(--revf-font-size-xs, 12px);
    font-weight: 800;
    color: var(--revf-text-secondary, #5b6b7a);
  }

  .revf-stack-table td[data-label=""]::before {
    content: none;
  }

  /* Right-aligned numeric cells read as ordinary values once stacked. */
  .revf-stack-table .revf-num {
    text-align: left;
  }

  /* The value side of a row must be able to shrink, or a long URL widens the
     card past the viewport instead of wrapping inside it. */
  .revf-stack-table td > * {
    min-width: 0;
    max-width: 100%;
  }
}
