/* =====================================================================
   payment.css — お支払いについて page (/payment/)
   ---------------------------------------------------------------------
   This page is a sibling of /app/ and deliberately loads css/app.css
   before this file: the hero, the four-fact strip, the ruled step
   columns, the two-column shot-beside-copy block, the feature table and
   the FAQ recipe are all already designed there, and re-cutting them
   here would be a second dialect of the same page family. The body
   carries BOTH `page-app` and `page-payment` so app.css's ink tokens
   (--ink-sky / --ink-amber / --ink-quiet, now global in base.css), its type scale
   and its reduced-motion block apply unchanged.

   Only what /app/ has no component for lives here, in source order:
     1. .pay-price     — 入会金 + the four monthly fees (css/fee.css)
     2. .pay-brands    — the accepted brands + wallets, as logo tiles
     3. .pay-safe      — the four reassurance cards
     4. .pay-callout   — a single emphasised note inside a section
     5. .pay-rules     — 振替・キャンセル・退会 as a definition table
     6. narrow phones

   Responsive contract: fluid from 320px up. The ramp this file actually
   ships, and why each step exists:
     1023  the two card grids go 2-up and share a 20px gutter
      767  .pay-safe goes 1-up; .pay-rules-table restacks into blocks
     1023  the fee table goes 2-up (css/fee.css)
      520  the fee table goes 1-up (css/fee.css)
      389  the hero frame drops its gutters so the mock keeps its 302px
      349  both mocks are scaled a second step to fit a 272px column
   (It previously claimed 520/767/1023. 520 is never used, and the --sp-7
   bug shipped through 767 — a width the contract named but nothing checked.
   Keep this list honest: it is the checklist a reviewer works from.)
   ===================================================================== */


/* ---------------------------------------------------------------------
   MEASURES — there are two, and everything on the page uses one of them.

   index.php sets the house rule and keeps to it: every content block sits
   at the container's full 1000px (14 of them) and every section header and
   short note sits at 720px (11 of them). Two edges, so the eye tracks one
   line down the left as it scrolls.

   This page had drifted to six: 1000 for the grids, 800 for the price and
   rules panels, 820 for the sign-off, 786 for the hero copy, 720 for the
   headers and 630 for the note. Nothing was wrong with any single value;
   the problem was that the left edge moved eleven times on the way down.

   The design system now owns both: --w-narrow (720px, base.css) for headers
   and notes, and the container for everything else. Content blocks declare
   no max-width at all — they inherit the container's, which is what
   index.php's blocks do.
--------------------------------------------------------------------- */


/* ---------------------------------------------------------------------
   0. HERO — /app/ hangs its phone off the corner of a desktop window
   shot, so .app-hero-phone is absolutely positioned and .app-hero-visual
   is only tall enough to clear the overhang. This page has no window
   mock, so that phone rides straight up over the headline. Here it is
   set STATIC and centred instead, inside a fixed-height frame that crops
   it to the top of the お支払い情報 screen — the registered cards, which
   is exactly what the headline promises — and fades the cut into the
   cream. The whole screen is shown further down, beside its own copy.
--------------------------------------------------------------------- */
.page-payment .app-hero-visual {
  width: 100%;
  max-width: 330px;
  /* Fixed, not clamped, and the fade is set in pixels rather than percent.
     Both follow from the same thing: the cut has to land BETWEEN two rows of
     the card list, and a percentage stop moves with the frame height while
     the rows do not. On a clamp(290,32vw,400) frame with the stop at 74% the
     fade began inside the VISA row at every width from 320 to 1132 — the
     first row of the list the headline is pointing at was the one row served
     half-ghosted. The list sits at 206-271 (VISA), 271-337 (Apple Pay) and
     337-403 (Link) inside this mock, so opaque to 271 gives a solid first
     row, a second row that fades, and a third that suggests more below. */
  height: 366px;
  margin: var(--sp-12) auto 0;
  /* Side gutters so the phone's drop shadow has somewhere to land: with the
     frame clipping flush to the bezel, the shadow was declared and then cut
     off on both edges, and the mock read as a panel rather than an object. */
  padding: 0 14px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 271px, transparent 366px);
          mask-image: linear-gradient(180deg, #000 0, #000 271px, transparent 366px);
}
/* display:block re-asserted — app.css hides the phone below 900px, where
   it would collide with the window mock this page does not have. */
.page-payment .app-hero-phone {
  display: block;
  position: static;
  width: 100%;
  filter: none;
}
/* zoom:1 deliberately cancels app-mock.css's site-wide narrow-phone net
   (0.9 below 420px, 0.8 below 360px): this frame does its own scaling at
   349px so the shot stays as large as the column allows. That leaves four
   separately-owned numbers holding the mock's fit — --content-pad-x
   (base.css), the 330px frame and 14px gutters here, and the 389/349
   breakpoints. Change any one and re-measure the 今後のお支払い予定 tiles,
   which need 302px of phone to lay out. */
.page-payment .app-hero-phone .app-phone {
  zoom: 1;
  box-shadow: 0 30px 60px -24px rgba(31, 26, 20, 0.28);
}
/* Out of the absolute corner and back into the hero's flex column, so it
   sits under the cropped shot rather than over the section below it. */
.page-payment .app-hero-caption {
  position: static;
  justify-content: center;
  margin-top: var(--sp-4);
  padding-bottom: var(--sp-12);
}
.page-payment .app-hero-caption::before { display: none; }

/* The 「アプリの中に」 block reuses /app/'s .app-platform. That section is
   tuned for platform-devices — a wide, short composition it can afford to
   scale up by 1.3 (app.css:978). The お支払い情報 phone is a tall single
   column, so it is scaled DOWN instead. 0.85 is a balance number, not a
   fitting one: at native size the pinned frame stands 735px against a text
   column of 548px, and the grid centres them, so 219px of the band was void
   beside the copy. 0.85 takes the frame to 625px and the overhang to 109px,
   which reads as a tall object beside a shorter one rather than a slab with
   text floating next to it. In-phone base type lands at 11.5px, still above
   the 0.76 the feature cards on this same page already ship (app.css:732).
   (735px is not itself out of range — /app/ carries a 786px phone — so this
   is not a correction, it is composition.) */
.page-payment .app-platform-visual .jse-mock { zoom: 0.85; }

/* Hold the screen at a real handset's proportions. Nothing else on the site
   pins a phone's height — every .app-phone is as tall as whatever fragment
   is poured into it — and that is exactly how this one reached 330 x 1010
   (ratio 3.06) while /app/'s own shots sit between 1.9 and 2.2. An iPhone's
   display is 19.5:9 = 2.167, so at the 330px screen width this frame gives
   (350 less the 10px bezel on each side) the screen is 715px and the outer
   frame 735px — ratio 2.10, which is the body ratio of the handset itself.
   partials/app/payment-schedule.php is written to come in just under that,
   so the spare pixels read as empty canvas below the last row, the way a
   real screen does. overflow:hidden is the guarantee, not the mechanism: if
   a future edit overruns, the shot stays phone-shaped and the surplus is
   clipped rather than stretching the frame back out. */
.page-payment .app-platform-visual .app-phone-screen {
  aspect-ratio: 9 / 19.5;
  overflow: hidden;
}
/* The pin alone is not a clip contract. .app-phone-screen is a flex column of
   status bar / body / home indicator (app-mock.css:473), and .app-phone-body
   is flex:1 with no min-height:0, so a body that overruns refuses to shrink
   and the overflow is taken off the BOTTOM of the screen — the home indicator
   goes first, then the last row is cut with a hard edge. Let the body shrink,
   and fade the cut the way every other clipped shot on this site does
   (app.css:941, app-mock.css:639 — the 40px band is the site constant). */
.page-payment .app-platform-visual .app-phone-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 40px), transparent 100%);
          mask-image: linear-gradient(180deg, #000 calc(100% - 40px), transparent 100%);
}
/* Scale the shot instead of reflowing it, so the fragment's height and the
   pinned frame shrink together and the fade never has anything to hide.
   Left to reflow, the frame narrows (width:100%) while the content does not,
   and the content overran the pin by 65px at 400px and 131px at 360px — the
   whole お支払い履歴 block, which is a third of what the heading promises.
   The frame is 350px wide and the column is the viewport less 48px of gutter,
   so 350 stops fitting at 398px; each step is the largest zoom that still
   fits at the narrowest viewport in its range (350 x 0.86 = 301 <= 302 at
   350px; 350 x 0.77 = 270 <= 272 at 320px). The hero's own ramp steps at
   389/349 rather than 399/349 because its frame is 330px, not 350px. */
.page-payment .app-platform-visual .app-phone {
  zoom: 1;                 /* cancel app-mock.css:616-621's narrow-phone net */
  width: 350px;
  max-width: none;
}
/* One step, not two: at 0.85 the frame is 297px and the column is the
   viewport less 48px of gutter, so it already fits every viewport down to
   346px and the old 399px step would now make the shot GROW on small
   phones. Below that, 0.76 gives 266px inside the 272px a 320px viewport
   leaves — and 0.76 is the site's own number at app.css:732. */
@media (max-width: 349px) {
  .page-payment .app-platform-visual .jse-mock { zoom: 0.76; }
}

/* Below ~350px the hero frame is narrower than the お支払い情報 mock's own
   350px design width, and the two 今後のお支払い予定 tiles squeeze until
   「¥16,500」 no longer fits its cell (13px short at 320px, 3px at 340px).
   Hold the frame at a fixed width and scale it instead of letting the mock
   reflow — the same lever /app/ pulls with zoom on .jse-mock. 310 x 0.86 =
   267px, inside the 272px the narrowest supported viewport leaves. */
/* Two steps down, both set by where the mock physically stops fitting.
   The shot needs 302px to lay out the 今後のお支払い予定 tiles, so below
   390px the gutters go first — at that width the shot needs the pixels more
   than it needs its shadow — and below 350px even the full frame is too
   narrow, so the mock is pinned to a fixed width and scaled to fit the
   272px the narrowest supported viewport leaves (310 x 0.86 = 267px). */
@media (max-width: 389px) {
  .page-payment .app-hero-visual { padding-inline: 0; }
}
@media (max-width: 349px) {
  .page-payment .app-hero-visual .app-phone { width: 310px; max-width: none; }
  .page-payment .app-hero-visual .jse-mock { zoom: 0.86; }
  /* zoom moves the rows with it: 271 x 0.86 = 233, 366 x 0.86 = 315. */
  .page-payment .app-hero-visual {
    height: 315px;
    -webkit-mask-image: linear-gradient(180deg, #000 0, #000 233px, transparent 315px);
            mask-image: linear-gradient(180deg, #000 0, #000 233px, transparent 315px);
  }
}


/* ---------------------------------------------------------------------
   0b. BAND RHYTHM
   Every other page on the site alternates white / cream strictly, with no
   two adjacent bands sharing a ground: /, /about/ and /app/ all do. That
   works there because each has an ODD number of content bands between the
   cream hero block and the cream CTA, so the run starts and ends white.
   This page has eight, so one pair has to share a ground. It is placed on
   安心のしくみ + 振替・退会 — the two "before you commit" sections, which
   read as one block — rather than anywhere the reader is still scanning.

   The two app.css sections below carry their own background and ignore
   .section-alt, so the ground they take is set here, not in the markup:
   .section-app-platform is pulled to cream to keep the run alternating,
   and .section-app-faq keeps app.css's white so the FAQ meets the cream
   CTA exactly as it does on /app/ and on the home page.
--------------------------------------------------------------------- */
.page-payment .section-app-platform { background: var(--bg-cream); }


/* ---------------------------------------------------------------------
   0c. PROSE MEASURE
   layout.css caps .section-desc at 42em with the note that "a JP measure
   past ~45 characters stops scanning", and legal.css caps its own long-form
   column at 40rem. .pay-callout was set to 720px to match app.css's centred
   .app-flow-note — but that note is centred text, where a short last line
   reads as deliberate, while these callouts are left-aligned prose in a box,
   where 48em left three of them stranding a three-to-five character last
   line at every width from 768px up. 42em is the site's own figure.

   Measured over 390 / 768 / 1024 / 1280px, short last lines drop from 20 to
   11 (10.3% of blocks to 5.6%, against /app/'s own 4.0%) with average line
   fill unchanged at 94.3%. `word-break: auto-phrase` would take it to 1.0%,
   but costs 8 points of line fill (86.1%): it can only break between
   phrases, so every line stops early and the rag opens up. That is why
   layout.css scopes auto-phrase to the display primitives and leaves
   running copy alone — and why this page does too.
--------------------------------------------------------------------- */


/* ---------------------------------------------------------------------
   1. PRICE PANEL — 入会金 once, then the four monthly fees.
   The panel itself is css/fee.css, the fee table the course pages use too:
   one white surface, one cell recipe, one figure style. It replaced a warm
   head band with a display figure, a ruled strip, a centred equation and a
   cream fine-print band — four treatments inside one section. Nothing about
   the table lives here any more; see fee.css.
--------------------------------------------------------------------- */


/* ---------------------------------------------------------------------
   2. ACCEPTANCE MARKS — the seven card brands plus the two wallets.

   These were wordmark pills ("VISA", "Mastercard" as styled text) because
   the page had no logo files. It has them now, and a parent scanning for
   "is my card on here?" recognises the mark long before they read a word.

   Every mark sits in one uniform tile rather than being set to a common
   height, because the set is not uniform: six of the seven card marks are
   self-contained coloured cards (ratio 1.00 to 1.60) while Visa ships as a
   bare wordmark at ratio 3.09 and Apple Pay as a bare glyph. Matched on
   height, Visa would tower over Mastercard; matched on width, it would
   vanish. A fixed tile with object-fit: contain lets each mark find its own
   size inside the same box, which is also how a checkout page shows them.
--------------------------------------------------------------------- */
.pay-brands {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-8);
  padding: 0;
  list-style: none;
}
.pay-brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 62px;
  height: 40px;
  padding: 5px 7px;
  border: 1px solid var(--border-warm);
  border-radius: var(--r-sm);
  background: var(--bg-white);
}
.pay-brand img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
}
/* Both wallet marks ship with their own outlined container — Apple's black
   rounded rect, Google's dark grey pill — so the tile's border would be a
   second frame around a frame. Drop ours and let theirs be the edge, and
   give them a touch more of the box, since an outline reads lighter than
   the solid card faces either side of them. */
.pay-brand--wallet {
  border-color: transparent;
  background: none;
  padding: 2px;
}

@media (max-width: 480px) {
  .pay-brands { gap: 6px; }
  .pay-brand { width: 54px; height: 35px; padding: 4px 6px; }
  .pay-brand--wallet { padding: 3px; }
}


/* ---------------------------------------------------------------------
   3. REASSURANCE CARDS — the four 「安心してよい理由」, built as index.php's
   .about-support-card: blue icon disc and a tilted ghost numeral. The
   method cards this file used to define were retired when section 4 moved
   onto app.css's .app-features, which already ships a richer card with a
   product-shot slot; there is no reason for this page to own a second,
   plainer card of its own.
--------------------------------------------------------------------- */
.pay-safe {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-6);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* index.php's .about-support-card, ported (this page does not load home.css):
   blue icon disc, the rotated ghost numeral top-right, no shadow. It replaces
   a 3px amber left rule that made these four read as the same object as the
   five amber notice boxes the page used to end its sections with. */
.pay-safe-item {
  position: relative;
  overflow: hidden;
  padding: var(--sp-6);
  background: var(--bg-white);
  border: 1px solid var(--border-warm);
  border-radius: var(--r-md);
  min-width: 0;
}
/* home.css:1726 — the tilt is the point: it is the one mark on the card that
   could not have been produced by a layout engine laying out a grid. */
.pay-safe-num {
  position: absolute;
  top: 0.65rem;
  right: 1rem;
  font-size: var(--fs-deco-lg);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--accent);
  opacity: 0.18;
  pointer-events: none;
  transform: rotate(-4deg);
}
/* home.css:1741 */
.pay-safe-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: rgba(0, 174, 239, 0.10);
  color: var(--primary);
  margin-bottom: var(--sp-4);
}
.pay-safe-icon svg { width: 24px; height: 24px; }
.pay-safe-title {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  font-weight: var(--fw-bold);
  color: var(--text-main);
  text-wrap: balance;
}
.pay-safe-text {
  margin: 0;
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body-sm);
  color: var(--text-light);
}
/* Only the three sides that can afford it shrink on a phone. The left
   padding and the rule's own inset stay at their desktop values, so the
   accent keeps the same clearance from the text at every width.

   This block used to ask for var(--sp-7). The ramp has no --sp-7 (it runs
   1,2,3,4,5,6,8,10,12,14,16,24), and an undefined custom property with no
   fallback makes the WHOLE shorthand invalid at computed-value time — so
   `padding` fell back to its initial value of 0 rather than to the desktop
   rule, dropping the copy flush against the border with the amber rule
   printed on top of it. Every var() on this page is now checked against
   the ramp. */
/* The 2-up grid tightens one step as the columns narrow. It lives HERE,
   below .pay-safe's own rule, and not in the block of whatever component it
   is being kept in step with: at equal specificity the last declaration
   wins, and the first attempt at this sat above .pay-safe's own gap and
   silently lost the cascade. (app.css:890 restacks .app-features to a single
   card per row at this width, so the two grids are no longer comparable —
   the gutters only had to agree while both were multi-column.) */
@media (max-width: 1023px) {
  .pay-safe { gap: var(--sp-5); }
}
@media (max-width: 767px) {
  .pay-safe { grid-template-columns: 1fr; }
  .pay-safe-item { padding: var(--sp-5); }
}


/* ---------------------------------------------------------------------
   5. CALLOUT — ONE per page.
   This shipped five times: at the foot of five consecutive sections, all
   identical, so the page read as heading -> grid -> box, three beats over
   and over, and the box stopped meaning "this one is the exception". Three
   of the five were demoted to app.css's unboxed .app-flow-note, one was
   absorbed into the 安心 sign-off beside the portrait, and this is the
   survivor: the pointer to /tokusho/ and /policy/, which is the only one
   that is a legal caveat rather than a paragraph in a frame.

   Re-cut with no fill, because --bg-warm is also the 入会金 row's ground and
   the rules table's header column — one tint doing three jobs signals none
   of them. It now carries the amber rule that used to run down the side of
   the four 安心 cards, which is where a marked passage belongs.
--------------------------------------------------------------------- */
.pay-callout {
  position: relative;
  max-width: var(--w-narrow);
  margin: var(--sp-10) auto 0;
  padding: var(--sp-1) 0 var(--sp-1) var(--sp-6);
}
.pay-callout::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  border-radius: var(--r-full);
  background: var(--accent);
}
.pay-callout p {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-main);
}
.pay-callout p + p { margin-top: var(--sp-3); }
.pay-callout em {
  font-style: normal;
  font-weight: var(--fw-bold);
  color: var(--ink-amber);
}
.pay-callout a {
  color: var(--ink-sky);
  font-weight: var(--fw-bold);
  text-decoration: underline;
  text-underline-offset: 3px;
}


/* ---------------------------------------------------------------------
   6. RULES TABLE — 振替・キャンセル・欠席・退会 against 「請求はどうなるか」.
   The one place on this page where the answer is a rule rather than a
   reassurance, so it is set as a plain two-column table and left to be
   read slowly. Restacks into blocks below 768px.
--------------------------------------------------------------------- */
.pay-rules {
  margin: 0 auto;
  background: var(--bg-white);
  border: 1px solid var(--border-warm);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.pay-rules-table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}
.pay-rules-table th,
.pay-rules-table td {
  padding: var(--sp-5) var(--sp-8);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  border-bottom: 1px solid var(--border-warm);
  vertical-align: top;
}
.pay-rules-table tbody th {
  /* In the table layout the column sizes to its longest label (259px at
     768–919, 30% above), as legal.css .legal-table th does. Phrase-aware
     wrapping applies once stacked (app.css .app-index-table). */
  width: 30%;
  white-space: nowrap;
  word-break: auto-phrase;
  font-weight: var(--fw-bold);
  color: var(--text-main);
  background: var(--bg-warm);
}
.pay-rules-table td { color: var(--text-light); }
.pay-rules-table tr:last-child th,
.pay-rules-table tr:last-child td { border-bottom: 0; }
.pay-rules-table strong { color: var(--text-main); font-weight: var(--fw-bold); }
@media (max-width: 767px) {
  .pay-rules-table tbody th,
  .pay-rules-table tbody td { display: block; width: auto; padding: var(--sp-4) var(--sp-5); }
  .pay-rules-table tbody th { border-bottom: 0; padding-bottom: var(--sp-2); white-space: normal; }
}


/* ---------------------------------------------------------------------
   7. SECTION TWEAKS — the few places this page needs to depart from
   app.css's spacing, plus the narrow-phone floor.
--------------------------------------------------------------------- */
/* The price panel and the rules table are the section's only content, so
   they take the section header's own gap rather than a card grid's. */
.section-pay-price .pay-price,
.section-pay-rules .pay-rules { margin-top: 0; }

/* A caption under a mockup, matching .app-hero-caption's quiet register. */
.pay-shot-caption {
  margin: var(--sp-4) 0 0;
  text-align: center;
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--ink-quiet);
}

/* Below 768px the restacked rules table carries its padding on the ROW, not
   the cells (the cells are set to 0 there), so tightening the cells here did
   nothing and the panel head pulled 4px left of its own rows. Target what
   actually holds the padding. */
@media (max-width: 360px) {
  .pay-rules-table tbody th,
  .pay-rules-table tbody td { padding-inline: var(--sp-4); }
}


/* ---------------------------------------------------------------------
   METHOD FEATURE CARDS
   Section 4 borrows /app/'s .app-features — the photo-topped three-up —
   with the product shot standing in for the photograph. On /app/ each
   card is an expandable card (.card--link + [data-xcard]); here there is
   no detail behind them, so they are the plain static variant and do not
   react to the pointer (css/app.css .app-feature:not(.card--link)).
   --------------------------------------------------------------------- */


/* ---------------------------------------------------------------------
   TWO-UP FLOW
   app.css's .app-flow is a three-across grid because /app/ always has
   three or six steps. 「引き落とされるのは、この2つのタイミングだけ。」 has
   two, and two items in a three-column grid leave a hole on the right that
   reads as a missing card. Narrowing the measure as well as the count is
   deliberate: it stops this section rhyming with the three-across flow in
   「カードが使えなかったときも」, which is the page's most literal repeat.
   --------------------------------------------------------------------- */
.app-flow--two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
/* app.css restacks .app-flow to one column at 600px, but its rule sits in an
   earlier stylesheet at the same specificity as the modifier above, so the
   modifier would win and hold two columns all the way down. Restate it on the
   site's own breakpoint rather than inventing a step for this one list. */
@media (max-width: 600px) {
  .app-flow--two { grid-template-columns: 1fr; }
}


/* ---------------------------------------------------------------------
   SIGN-OFF — the portrait, and the one paragraph written in first person.
   Ported from index.php's .instructor-portrait (home.css:2341) because this
   page does not load home.css. The polaroid's tilt, the washi tape and the
   handwritten signature are the site's only deliberately imperfect object,
   and the payment page had nothing of the kind anywhere in it: every edge
   was axis-aligned, which is most of why it read as machine-made.

   The credential stamp is left off on purpose. On index.php the stamp is
   the argument (this teacher is qualified); here the caption's job is to
   put a name and a face on the person accountable for the money.
   --------------------------------------------------------------------- */
.pay-signoff {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: var(--sp-12);
  align-items: center;
  margin: var(--sp-14) auto 0;
}
.pay-portrait {
  position: relative;
  margin: 0;
  padding: 0.75rem 0.75rem 3rem;
  background: #fff;
  border: 1px solid var(--border-warm);
  border-radius: 6px;
  box-shadow:
    0 1px 0 rgba(0, 0, 0, 0.04),
    0 18px 38px rgba(35, 25, 15, 0.16);
  transform: rotate(-1.8deg);
}
/* Washi tape, mirrored corners — home.css:2355. Rotated the opposite way
   from index.php's so the two portraits are not the same object twice. */
.pay-portrait::before,
.pay-portrait::after {
  content: '';
  position: absolute;
  width: 100px;
  height: 24px;
  background: linear-gradient(
    180deg,
    rgba(255, 238, 180, 0)    0%,
    rgba(255, 238, 180, 0.5) 14%,
    rgba(253, 230, 160, 0.55) 50%,
    rgba(255, 238, 180, 0.5) 86%,
    rgba(255, 238, 180, 0)  100%
  );
  box-shadow: 0 2px 5px rgba(35, 25, 15, 0.07);
  z-index: 3;
  pointer-events: none;
}
.pay-portrait::before { top: -2px; left: -38px; transform: rotate(-42deg); }
.pay-portrait::after  { bottom: -2px; right: -38px; transform: rotate(-42deg); }
.pay-portrait-frame {
  position: relative;
  border-radius: 3px;
  overflow: hidden;
  aspect-ratio: 1 / 1;
  background: #f3efe9;
}
.pay-portrait-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: saturate(0.95) contrast(0.97);
}
/* The vignette keeps the photo from reading as a flat stock asset dropped
   into a box — home.css:2442. */
.pay-portrait-frame::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 35%, rgba(255, 255, 255, 0) 55%, rgba(35, 25, 15, 0.10) 100%);
  pointer-events: none;
}
.pay-portrait-caption {
  position: absolute;
  left: 0.9rem;
  right: 0.9rem;
  bottom: 0.8rem;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}
.pay-portrait-sig {
  font-size: var(--fs-deco);
  font-weight: 700;
  color: var(--primary);
  line-height: 1;
  transform: rotate(-2deg);
  letter-spacing: 0;
}
.pay-portrait-meta {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  color: var(--ink-quiet);
  letter-spacing: 0.04em;
  text-align: right;
}
.pay-signoff-body p {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-light);
}
.pay-signoff-body p + p { margin-top: var(--sp-3); }
.pay-signoff-body em {
  font-style: normal;
  font-weight: var(--fw-bold);
  color: var(--ink-amber);
}
/* The only sentence on the page written in the first person. It is set
   apart so it reads as a person talking, not as another body paragraph. */
.pay-signoff-ask {
  padding-top: var(--sp-4);
  border-top: 1px dashed var(--border-warm);
  color: var(--text-main) !important;
  font-weight: var(--fw-bold);
}
.pay-signoff-ask a {
  color: var(--ink-sky);
  text-decoration: underline;
  text-underline-offset: 3px;
}
@media (max-width: 860px) {
  .pay-signoff {
    grid-template-columns: 1fr;
    gap: var(--sp-8);
    justify-items: center;
    max-width: var(--w-narrow);   /* stacked, the letter is a text block */
  }
  .pay-portrait { max-width: 280px; }
  .pay-signoff-body { text-align: left; }
}
/* The tape hangs 38px off each side of the polaroid, which is what makes it
   read as stuck on rather than drawn on. Once the column is as narrow as the
   portrait, that overhang is 14px wider than the viewport and the whole page
   gains a horizontal scroll — invisible until you reach the foot of the page,
   which is why it shipped. Clipping is not the fix: overflow:hidden on the
   block would take the polaroid's drop shadow with it and flatten the card.
   Pull the tape in instead; at this size a shorter overhang reads the same. */
@media (max-width: 400px) {
  .pay-portrait::before { left: -18px; }
  .pay-portrait::after  { right: -18px; }
}


/* ---------------------------------------------------------------------
   GROUND TEXTURE
   index.php lays a gold dot field over two whole sections (home.css:2276
   on 講師紹介, home.css:3198 on 合格までの流れ) so the eye has something to
   rest on between cards. Every ground on this page was a flat fill, which
   is most of why the cream bands read as empty rather than as paper.

   It goes on the two cream bands that sit back to back — 安心のしくみ and
   振替・退会. The band-rhythm note above explains why those two share a
   ground; giving only the second one texture means the seam between them
   is visible without breaking the alternation the rest of the site keeps.
   --------------------------------------------------------------------- */
.page-payment .section-pay-rules {
  position: relative;
  overflow: hidden;
}
.page-payment .section-pay-rules::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle, rgba(245, 158, 11, 0.08) 1px, transparent 1.2px);
  background-size: 28px 28px;
  opacity: 0.55;
  pointer-events: none;
}
.page-payment .section-pay-rules > .container { position: relative; }

/* The rules table shipped identical to the price panel — same radius, same
   border, same shadow — so the two read as twins forty screens apart. The
   price panel is the one a reader came for and keeps the card shadow
   (css/fee.css); this one drops to the flat tier. */
.pay-rules { box-shadow: none; }


/* The FAQ closing card (.faq-cta) is part of the shared FAQ component. */


/* The Stripe mark under the 安心のしくみ header. Deliberately smaller than
   the acceptance marks above: those answer "will my card work?", which is a
   question the reader is actively asking, while this one only has to confirm
   a name the copy has already given them three times. */
.pay-powered {
  margin: var(--sp-5) 0 0;
  text-align: center;
  line-height: 0;
}
.pay-powered img {
  display: inline-block;
  width: 76px;
  height: auto;
}
