| @@ -144,4 +144,227 @@ | ||
| 144 | 144 | line-height: 32px; /* 34px height minus 1px border top/bottom */ |
| 145 | 145 | padding: 4px 12px; |
| 146 | 146 | border-radius: 6px; |
| 147 | 147 | } |
| 148 | + | |
| 149 | +/* Switch Fee type picker: shrink to its content instead of filling the row. */ | |
| 150 | +.subscrpt-switch-fee-type .wpsubs-adv-select__trigger { | |
| 151 | + width: max-content; | |
| 152 | + min-width: unset; | |
| 153 | +} | |
| 154 | + | |
| 155 | +/* ────────────────────────────────────────────────────────────────────────── | |
| 156 | + Page header — the title/description/rule use the shared inline markup from | |
| 157 | + the other admin pages (see views/settings.php). Only the Save button keeps a | |
| 158 | + class, so it doesn't stretch in the flex title row. | |
| 159 | + ────────────────────────────────────────────────────────────────────────── */ | |
| 160 | + | |
| 161 | +.subscrpt-settings__save { | |
| 162 | + flex: 0 0 auto; | |
| 163 | +} | |
| 164 | + | |
| 165 | +/* ────────────────────────────────────────────────────────────────────────── | |
| 166 | + Rail and panels | |
| 167 | + Every panel is in the DOM on every request, because the form posts to | |
| 168 | + options.php and an unrendered field is a field that saves nothing. | |
| 169 | + ────────────────────────────────────────────────────────────────────────── */ | |
| 170 | + | |
| 171 | +.subscrpt-settings__layout { | |
| 172 | + display: grid; | |
| 173 | + grid-template-columns: 216px minmax(0, 1fr); | |
| 174 | + gap: 20px; | |
| 175 | + align-items: start; | |
| 176 | +} | |
| 177 | + | |
| 178 | +/* The rail and the panel share a top edge, but their text does not: a field | |
| 179 | + label sits under the card's 1px border and 20px padding, a rail label under | |
| 180 | + the item's own 7px. The 14px difference is that gap closed, so the first | |
| 181 | + section name and the first setting's label land on the same line. */ | |
| 182 | +.subscrpt-settings__sidebar { | |
| 183 | + position: sticky; | |
| 184 | + top: 104px; | |
| 185 | + padding-top: 14px; | |
| 186 | + max-height: calc(100vh - 140px); | |
| 187 | + overflow-y: auto; | |
| 188 | + overscroll-behavior: contain; | |
| 189 | +} | |
| 190 | + | |
| 191 | +/* The sidebar rail itself is the reusable `wpsubs-vnav` component | |
| 192 | + (admin-components/vnav.css); only its placement lives here. */ | |
| 193 | + | |
| 194 | +/* Stacks the panels in the `All` category, and holds a single one otherwise. */ | |
| 195 | +.subscrpt-settings__panels { | |
| 196 | + display: flex; | |
| 197 | + flex-direction: column; | |
| 198 | + gap: 16px; | |
| 199 | +} | |
| 200 | + | |
| 201 | +.subscrpt-settings__panel { | |
| 202 | + padding: 20px 24px; | |
| 203 | +} | |
| 204 | + | |
| 205 | +/* The `hidden` attribute is only a user-agent `display: none`, so any class | |
| 206 | + that sets `display` beats it. Panels carry `wpsubs-table-card`, so say it | |
| 207 | + again with the weight the attribute cannot bring on its own. */ | |
| 208 | +.subscrpt-settings__panel[hidden] { | |
| 209 | + display: none !important; | |
| 210 | +} | |
| 211 | + | |
| 212 | +.subscrpt-settings__rule { | |
| 213 | + border-top: 1px solid var(--wpsubs-border, #f1f5f9); | |
| 214 | + margin: 16px 0; | |
| 215 | +} | |
| 216 | + | |
| 217 | +@media screen and (max-width: 960px) { | |
| 218 | + .subscrpt-settings__layout { | |
| 219 | + grid-template-columns: minmax(0, 1fr); | |
| 220 | + } | |
| 221 | + | |
| 222 | + .subscrpt-settings__sidebar { | |
| 223 | + position: static; | |
| 224 | + max-height: none; | |
| 225 | + overflow: visible; | |
| 226 | + } | |
| 227 | + | |
| 228 | + .subscrpt-settings__sidebar .wpsubs-vnav { | |
| 229 | + flex-direction: row; | |
| 230 | + flex-wrap: wrap; | |
| 231 | + } | |
| 232 | +} | |
| 233 | + | |
| 234 | +/* -------------------------------------------------------------------------- | |
| 235 | + Cancellation Flow | |
| 236 | + | |
| 237 | + A wide tab panel with an options rail beside it. Deliberately not the | |
| 238 | + settings layout above: that one leads with a 216px nav rail and makes its | |
| 239 | + sidebar sticky and scrollable, which is right for navigation and wrong for | |
| 240 | + a panel of fields. | |
| 241 | + -------------------------------------------------------------------------- */ | |
| 242 | +.subscrpt-flow__layout { | |
| 243 | + display: grid; | |
| 244 | + grid-template-columns: minmax(0, 1fr) 340px; | |
| 245 | + gap: 20px; | |
| 246 | + align-items: start; | |
| 247 | +} | |
| 248 | + | |
| 249 | +@media (max-width: 960px) { | |
| 250 | + .subscrpt-flow__layout { | |
| 251 | + grid-template-columns: minmax(0, 1fr); | |
| 252 | + } | |
| 253 | +} | |
| 254 | + | |
| 255 | +/* The options rail is far narrower than a settings panel, so its fields stack | |
| 256 | + rather than using the shared 220px label / 260px control row, which needs | |
| 257 | + about 500px before it fits. */ | |
| 258 | +.subscrpt-flow__options .wpsubs-settings-field { | |
| 259 | + flex-direction: column; | |
| 260 | + gap: 8px; | |
| 261 | +} | |
| 262 | + | |
| 263 | +.subscrpt-flow__options .wpsubs-settings-field + .wpsubs-settings-field { | |
| 264 | + margin-top: 18px; | |
| 265 | +} | |
| 266 | + | |
| 267 | +.subscrpt-flow__options .wpsubs-settings-field__label { | |
| 268 | + flex: 0 0 auto; | |
| 269 | +} | |
| 270 | + | |
| 271 | +.subscrpt-flow__options .wpsubs-settings-field__control .wpsubs-input, | |
| 272 | +.subscrpt-flow__options .wpsubs-settings-field__control .wpsubs-select, | |
| 273 | +.subscrpt-flow__options .wpsubs-settings-field__control .wpsubs-adv-select__trigger { | |
| 274 | + min-width: 0; | |
| 275 | + max-width: 100%; | |
| 276 | + width: 100%; | |
| 277 | +} | |
| 278 | + | |
| 279 | +/* Both panels share one padding rhythm so the two columns line up. */ | |
| 280 | +.subscrpt-flow__panel { | |
| 281 | + padding: 20px; | |
| 282 | +} | |
| 283 | + | |
| 284 | +/* The saved reason list: the same row treatment the manage modal uses, so the | |
| 285 | + page and the modal read as one thing. Numbered, because the order is what a | |
| 286 | + customer sees. */ | |
| 287 | +.subscrpt-flow__reasons { | |
| 288 | + list-style: none; | |
| 289 | + margin: 0 0 18px; | |
| 290 | + padding: 0; | |
| 291 | + counter-reset: subscrpt-reason; | |
| 292 | +} | |
| 293 | + | |
| 294 | +.subscrpt-flow__reasons li { | |
| 295 | + display: flex; | |
| 296 | + align-items: center; | |
| 297 | + gap: 12px; | |
| 298 | + padding: 10px 14px; | |
| 299 | + border: 1px solid var(--wpsubs-border, #e5e7eb); | |
| 300 | + border-radius: var(--wpsubs-radius-sm, 5px); | |
| 301 | + background: var(--wpsubs-surface, #fff); | |
| 302 | + font-size: 13px; | |
| 303 | + color: var(--wpsubs-text, #374151); | |
| 304 | +} | |
| 305 | + | |
| 306 | +.subscrpt-flow__reasons li + li { | |
| 307 | + margin-top: 8px; | |
| 308 | +} | |
| 309 | + | |
| 310 | +.subscrpt-flow__reasons li::before { | |
| 311 | + counter-increment: subscrpt-reason; | |
| 312 | + content: counter(subscrpt-reason); | |
| 313 | + flex: 0 0 auto; | |
| 314 | + display: inline-flex; | |
| 315 | + align-items: center; | |
| 316 | + justify-content: center; | |
| 317 | + width: 22px; | |
| 318 | + height: 22px; | |
| 319 | + border-radius: 999px; | |
| 320 | + background: var(--wpsubs-surface-muted, #f9fafb); | |
| 321 | + color: var(--wpsubs-text-muted, #6b7280); | |
| 322 | + font-size: 11px; | |
| 323 | + font-weight: 600; | |
| 324 | +} | |
| 325 | + | |
| 326 | +/* "Other" is not one of the store's reasons: the survey adds it while the | |
| 327 | + comment box is on. Shown in its place, but visibly not editable. */ | |
| 328 | +.subscrpt-flow__reasons li.subscrpt-flow__reason--auto { | |
| 329 | + border-style: dashed; | |
| 330 | + background: var(--wpsubs-surface-muted, #f9fafb); | |
| 331 | + color: var(--wpsubs-text-muted, #6b7280); | |
| 332 | +} | |
| 333 | + | |
| 334 | +.subscrpt-flow__reason-note { | |
| 335 | + margin-left: auto; | |
| 336 | + font-size: 12px; | |
| 337 | + color: var(--wpsubs-text-subtle, #9ca3af); | |
| 338 | +} | |
| 339 | + | |
| 340 | +/* Shown once the list has been edited and not yet saved. */ | |
| 341 | +.subscrpt-flow__unsaved { | |
| 342 | + font-size: 13px; | |
| 343 | + color: var(--wpsubs-text-muted, #6b7280); | |
| 344 | +} | |
| 345 | + | |
| 346 | +.subscrpt-flow__empty { | |
| 347 | + margin: 0 0 18px; | |
| 348 | + color: var(--wpsubs-text-subtle, #9ca3af); | |
| 349 | + font-size: 13px; | |
| 350 | +} | |
| 351 | + | |
| 352 | +/* The reasons control carries no label of its own - the tab names the panel. | |
| 353 | + The label element is still emitted (with whitespace, so `:empty` never | |
| 354 | + matches) and its `flex: 0 0 220px` becomes a 220px tall gap once the row | |
| 355 | + stacks, so hide it outright. */ | |
| 356 | +.subscrpt-flow__panel--reasons .wpsubs-settings-field { | |
| 357 | + flex-direction: column; | |
| 358 | + gap: 10px; | |
| 359 | +} | |
| 360 | + | |
| 361 | +.subscrpt-flow__panel--reasons .wpsubs-settings-field__label { | |
| 362 | + display: none; | |
| 363 | +} | |
| 364 | + | |
| 365 | +.subscrpt-flow__note { | |
| 366 | + margin: 18px 0 0; | |
| 367 | + color: var(--wpsubs-text-muted, #6b7280); | |
| 368 | + font-size: 12px; | |
| 369 | + line-height: 1.6; | |
| 370 | +} | |